CF653F. Paper task
生活随笔
收集整理的這篇文章主要介紹了
CF653F. Paper task
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
CF653F. Paper task
簡要題面
給定括號序列SSS,求其中本質不同合法括號序列個數。(∣S∣≤5?105|S|\leq 5*10^5∣S∣≤5?105)
Solution
感覺用了一個很麻煩的方法。
我們可以考慮枚舉本質不同串的右端點,每次動態地在SAMSAMSAM里面加入末尾元素,新增的本質不同后綴個數rrr即為lenlst?lenfa[lst]len_{lst}-len_{fa[lst]}lenlst??lenfa[lst]?,顯然新增的本質不同串的起點是[1,r][1,r][1,r],終點是iii。
現在我們考慮有多少起點在[1,r][1,r][1,r]中的序列合法,我們對于1..i1..i1..i做一個括號匹配,倘若有左括號沒被消掉,則起點只可能在沒消掉的左括號右邊,令l=max(stk[i])l=max(stk[i])l=max(stk[i]),表示最右邊的未消掉的左括號。
此時起點在[l+1,r][l+1,r][l+1,r]的串顯然只需要滿足一個條件——左右括號個數相等即可(因為此時左括號個數不可能多于右括號),因此建一個線段樹維護區間內左右括號個數差即可。
Code
#include <vector> #include <list> #include <map> #include <set> #include <deque> #include <queue> #include <stack> #include <bitset> #include <algorithm> #include <functional> #include <numeric> #include <utility> #include <sstream> #include <iostream> #include <iomanip> #include <cstdio> #include <cmath> #include <cstdlib> #include <cctype> #include <string> #include <cstring> #include <ctime> #include <cassert> #include <string.h> //#include <unordered_set> //#include <unordered_map> //#include <bits/stdc++.h>#define MP(A,B) make_pair(A,B) #define PB(A) push_back(A) #define SIZE(A) ((int)A.size()) #define LEN(A) ((int)A.length()) #define FOR(i,a,b) for(int i=(a);i<(b);++i) #define fi first #define se secondusing namespace std;template<typename T>inline bool upmin(T &x,T y) { return y<x?x=y,1:0; } template<typename T>inline bool upmax(T &x,T y) { return x<y?x=y,1:0; }typedef long long ll; typedef unsigned long long ull; typedef long double lod; typedef pair<int,int> PR; typedef vector<int> VI;const lod eps=1e-15; const lod pi=acos(-1); const int oo=1<<30; const ll loo=1ll<<62; const int mods=1e9+7; const int MAXN=500005; const int INF=0x3f3f3f3f;//1061109567 /*--------------------------------------------------------------------*/ inline int read() {int f=1,x=0; char c=getchar();while (c<'0'||c>'9') { if (c=='-') f=-1; c=getchar(); }while (c>='0'&&c<='9') { x=(x<<3)+(x<<1)+(c^48); c=getchar(); }return x*f; } char st[MAXN]; int n,s[MAXN],stk[MAXN],top=0; PR S[MAXN<<2]; void build(int x,int l,int r) {if (l==r) { S[x]=MP(s[l],1); return; }int mid=(l+r)>>1;build(x<<1,l,mid);build(x<<1|1,mid+1,r);S[x].fi=min(S[x<<1].fi,S[x<<1|1].fi),S[x].se=0;if (S[x].fi==S[x<<1].fi) S[x].se+=S[x<<1].se;if (S[x].fi==S[x<<1|1].fi) S[x].se+=S[x<<1|1].se; } PR query(int x,int l,int r,int L,int R) {if (l>=L&&r<=R) return S[x];int mid=(l+r)>>1;if (R<=mid) return query(x<<1,l,mid,L,R);else if (L>mid) return query(x<<1|1,mid+1,r,L,R);else{PR X=query(x<<1,l,mid,L,mid),Y=query(x<<1|1,mid+1,r,mid+1,R);if (X.fi==Y.fi) return MP(X.fi,X.se+Y.se);return (X.fi<Y.fi)?X:Y;} } int len[MAXN<<1],t[MAXN<<1][2],fa[MAXN<<1],sz=2,lst=1; void insert(int c) {int p=lst,np=lst=sz++;len[np]=len[p]+1;for (;p&&!t[p][c];p=fa[p]) t[p][c]=np;if (!p) { fa[np]=1; return; }int q=t[p][c];if (len[q]==len[p]+1) fa[np]=q;else{int nq=sz++;len[nq]=len[p]+1;fa[nq]=fa[q];fa[np]=fa[q]=nq;memcpy(t[nq],t[q],sizeof t[0]);for (;t[p][c]==q;p=fa[p]) t[p][c]=nq;} } signed main() {n=read();scanf("%s",st+1);for (int i=1;i<=n;i++) s[i]=s[i-1]+(st[i]=='('?1:-1);build(1,0,n-1);ll ans=0;for (int i=1;i<=n;i++){if (st[i]=='(') stk[++top]=i;else if (top) stk[top--]=0;int l=stk[top]+1;insert(st[i]==')');int r=len[lst]-len[fa[lst]];if (l<=r){PR t=query(1,0,n-1,l-1,r-1);if (t.fi==s[i]) ans+=t.se;}}printf("%lld\n",ans);return 0; } 創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的CF653F. Paper task的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 注册AppStore开发者账号以及收款设
- 下一篇: 程序模拟网易163邮箱注册帮助文档