2022NOIPA层联测4
正手一个[南猪入侵],反手一个[万箭齐发],我的[桃]真的快用完了……OI啊(MP),我(ZP)劝你出手前考虑一下,如果我DEAD了,你可就没牌了……话说难道我没有跳过忠吗??
问题 A: 【2022NOIP联测4 10月6日】字符串还原
string用熟了,于是就忘了它的时间复杂度,TLE 40 不过用起来是真的简单,10分钟不到就搞定了。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> using namespace std; int n, mid, flag; string ans, u; inline int read() { int x = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') { f = -1; } ch = getchar(); } while(ch >= '0' && ch <= '9') { x = (x << 1) + (x << 3) + (ch^48); ch = getchar(); } return x * f; } int main() { n = read(); mid = n/2; cin >> u; for(int i=1; i<n-1; i++) { string t = u.substr(0, i) + u.substr(i+1); string s1 = t.substr(0, mid), s2 = t.substr(mid); if(s1 == s2) { if(!flag) {ans = s1; flag++;} else flag++; } } string t = u.substr(1); string s1 = t.substr(0, mid), s2 = t.substr(mid); if(s1 == s2) { if(!flag) {ans = s1; flag++;} else flag++; } t.clear(); s1.clear(); s2.clear(); t = u.substr(0, n-1); s1 = t.substr(0, mid); s2 = t.substr(mid); if(s1 == s2) { if(!flag) {ans = s1; flag++;} else flag++; } if(flag > 1) printf("NOT UNIQUE\n"); else if(!flag) printf("NOT POSSIBLE\n"); else cout << ans << endl; return 0; }
于是开始改hash,套用原来的string,TLE 95是因为每次答案的hash值我居然又拿出个string计算了一下。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> using namespace std; typedef unsigned long long ll; const int maxn = 2e6 + 30; int n, mid, flag; //ll mod = 1234567891; ll f[maxn], m[maxn], B = 131, lstans, nowans; string ans, u; inline int read() { int x = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') { f = -1; } ch = getchar(); } while(ch >= '0' && ch <= '9') { x = (x << 1) + (x << 3) + (ch^48); ch = getchar(); } return x * f; } int main() { n = read(); mid = n/2; cin >> u; m[0] = 1; for(int i=1; i<=n; i++) m[i] = m[i-1] * B; n = u.length(); f[0] = u[0] - 'A' + 1; for(int i=1; i<n; i++) { f[i] = f[i-1] * B + (u[i]-'A'+1); } for(int i=1; i<=mid; i++) { ll h1 = f[i-1]*m[mid-i]+f[mid]-f[i]*m[mid-i]; ll h2 = f[n-1]-f[mid]*m[n-mid-1]; if(h1 == h2) { if(!flag) { string t = u.substr(0, i) + u.substr(i+1); string s1 = t.substr(0, mid), s2 = t.substr(mid); ans = s1; flag++; for(int i=0; i<ans.length(); i++) { lstans = lstans * B + (ans[i]-'A'+1); } } else { string t = u.substr(0, i) + u.substr(i+1); string s1 = t.substr(0, mid), s2 = t.substr(mid); nowans = 0; for(int i=0; i<s1.length(); i++) { nowans = nowans * B + (s1[i]-'A'+1); } if(nowans == lstans) continue; else { printf("NOT UNIQUE\n"); exit(0); } } } } for(int i=mid+1; i<n-1; i++) { ll h1 = f[mid-1]; ll h2 = f[n-1]-f[i]*m[n-i-1]+(f[i-1]-f[mid-1]*m[i-mid])*m[n-i-1]; if(h1 == h2) { if(!flag) { string t = u.substr(0, i) + u.substr(i+1); string s1 = t.substr(0, mid), s2 = t.substr(mid); ans = s1; flag++; for(int i=0; i<ans.length(); i++) { lstans = lstans * B + (ans[i]-'A'+1); } } else { string t = u.substr(0, i) + u.substr(i+1); string s1 = t.substr(0, mid), s2 = t.substr(mid); nowans = 0; for(int i=0; i<s1.length(); i++) { nowans = nowans * B + (s1[i]-'A'+1); } if(nowans == lstans) continue; else { printf("NOT UNIQUE\n"); exit(0); } } } } ll h1 = f[mid]-f[0]*m[mid], h2 = f[n-1]-f[mid]*m[mid]; if(h1 == h2) { if(!flag) { string t = u.substr(1); string s1 = t.substr(0, mid), s2 = t.substr(mid); ans = s1; flag++; for(int i=0; i<ans.length(); i++) { lstans = lstans * B + (ans[i]-'A'+1); } } else { string t = u.substr(1); string s1 = t.substr(0, mid), s2 = t.substr(mid); nowans = 0; for(int i=0; i<s1.length(); i++) { nowans = nowans * B + (s1[i]-'A'+1); } if(nowans != lstans) { printf("NOT UNIQUE\n"); exit(0); } } } h1 = f[mid-1]; h2 = f[n-2]-f[mid-1]*m[mid]; if(h1 == h2) { if(!flag) { string t = u.substr(0, n-1); string s1 = t.substr(0, mid), s2 = t.substr(mid); ans = s1; flag++; for(int i=0; i<ans.length(); i++) { lstans = lstans * B + (ans[i]-'A'+1); } } else { string t = u.substr(0, n-1); string s1 = t.substr(0, mid), s2 = t.substr(mid); nowans = 0; for(int i=0; i<s1.length(); i++) { nowans = nowans * B + (s1[i]-'A'+1); } if(nowans != lstans) { printf("NOT UNIQUE\n"); exit(0); } } } if(!flag) printf("NOT POSSIBLE\n"); else cout << ans << endl; return 0; }
由分类讨论发现得到答案并不需要两个中转string,可以直接拿,并且发现答案的hash已经记录过,然后A个T1居然花了一下午!?
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> using namespace std; typedef unsigned long long ll; const int maxn = 2e6 + 30; int n, mid, flag; //ll mod = 1234567891; ll f[maxn], m[maxn], B = 131, lstans, nowans; string ans, u; inline int read() { int x = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') { f = -1; } ch = getchar(); } while(ch >= '0' && ch <= '9') { x = (x << 1) + (x << 3) + (ch^48); ch = getchar(); } return x * f; } int main() { n = read(); mid = n/2; cin >> u; m[0] = 1; for(int i=1; i<=n; i++) m[i] = m[i-1] * B; n = u.length(); f[0] = u[0] - 'A' + 1; for(int i=1; i<n; i++) { f[i] = f[i-1] * B + (u[i]-'A'+1); } for(int i=1; i<=mid; i++) { ll h1 = f[i-1]*m[mid-i]+f[mid]-f[i]*m[mid-i]; ll h2 = f[n-1]-f[mid]*m[n-mid-1]; if(h1 == h2) { if(!flag) { string s1 = u.substr(mid+1); ans = s1; flag++; lstans = h1; } else { nowans = h1; if(nowans == lstans) continue; else { printf("NOT UNIQUE\n"); exit(0); } } } } for(int i=mid+1; i<n-1; i++) { ll h1 = f[mid-1]; ll h2 = f[n-1]-f[i]*m[n-i-1]+(f[i-1]-f[mid-1]*m[i-mid])*m[n-i-1]; if(h1 == h2) { if(!flag) { string s1 = u.substr(0, mid); ans = s1; flag++; lstans = h1; } else { nowans = h1; if(nowans == lstans) continue; else { printf("NOT UNIQUE\n"); exit(0); } } } } ll h1 = f[mid]-f[0]*m[mid], h2 = f[n-1]-f[mid]*m[mid]; if(h1 == h2) { if(!flag) { string s1 = u.substr(mid+1); ans = s1; flag++; lstans = h1; } else { nowans = h1; if(nowans != lstans) { printf("NOT UNIQUE\n"); exit(0); } } } h1 = f[mid-1]; h2 = f[n-2]-f[mid-1]*m[mid]; if(h1 == h2) { if(!flag) { string s1 = u.substr(0, mid); ans = s1; flag++; lstans = h1; } else { nowans = h1; if(nowans != lstans) { printf("NOT UNIQUE\n"); exit(0); } } } if(!flag) printf("NOT POSSIBLE\n"); else cout << ans << endl; return 0; }
注意事项就是判断重复是作为答案的字符串不能重复,而不是断点必须取同一个,感谢cr的提醒。我本来以为自动溢出会被卡的,毕竟大佬们都在用双模数,然而居然没卡我qwq
至于其他3个题去哪了……emmm……我并不会……
不过既然下发标程了,我存个档:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<cstring> #include<iostream> #include<stdlib.h> #include<ctime> #include<string> #include<cmath> #include<algorithm> #include<vector> #include<set> #include<map> #include<queue> #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define per(i,a,b) for(int i=(a);i>=(b);i--) using namespace std; inline void read(int &x){ x=0;char ch=getchar();int f=1; while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} x*=f; } inline void judge(){ freopen("monkey.in","r",stdin); freopen("monkey.out","w",stdout); } const int maxn=1000005,mod=1e9+7; char s[maxn]; int a[maxn],f[maxn],n,trans[maxn][2],sum[maxn],parent[maxn]; int main(){ //judge(); scanf("%s",s+1);n=strlen(s+1); rep(i,1,n)a[i]=s[i]-'0'; rep(i,1,n)trans[i][a[i]]=i+1; trans[1][a[1]^1]=1;parent[1]=0;trans[0][0]=1;trans[0][1]=1; rep(i,2,n){ parent[i]=trans[parent[i-1]][a[i-1]]; trans[i][a[i]^1]=trans[parent[i]][a[i]^1]; }f[1]=sum[1]=1; // rep(i,1,n)printf("%d\n",parent[i]); rep(i,2,n){ sum[i]=sum[i-1]; int p=trans[i][a[i]^1]; f[i]=(sum[i]-sum[p-1]+1+(i-p)+mod)%mod; sum[i]=(sum[i-1]+f[i])%mod; } // rep(i,1,n)printf("%d\n",f[i]); int ans=sum[n]+n; ans%=mod; cout<<ans<<endl; return 0; }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstring> #include <cstdio> #include <cstdlib> #include <vector> #include <set> #define For(i, j, k) for (int i = j; i <= k; i++) #define Forr(i, j, k) for (int i = j; i >= k; i--) using namespace std; typedef long long LL; const int N = 1e6 + 10; LL sumc[N]; struct Segment_Tree { const static int NODE = 1 << 21; int lc[NODE], rc[NODE], addv[NODE], node; LL sum[NODE], sqr[NODE]; #define M ((L + R) >> 1) void modify(int &o, int L, int R, int l, int r) { if (!o) o = ++node; if (l <= L && R <= r) { addv[o]++; } else { if (l <= M) modify(lc[o], L, M, l, r); if (r > M) modify(rc[o], M + 1, R, l, r); } sum[o] = sum[lc[o]] + sum[rc[o]] + (sumc[R] - sumc[L - 1]) * addv[o]; sqr[o] = sqr[lc[o]] + sqr[rc[o]] + 2ll * addv[o] * sum[o] - (sumc[R] - sumc[L - 1])\ * addv[o] * addv[o]; } #undef M }T; struct Suffix_Automaton { int pre[N], ch[N][26], Max[N]; int node, lst; void extend(int c) { int p = lst; if (ch[p][c]) { int q = ch[p][c]; if (Max[q] == Max[p] + 1) { lst = q; return; } int nq = ++node; For(i, 0, 25) ch[nq][i] = ch[q][i]; pre[nq] = pre[q]; pre[q] = nq; Max[nq] = Max[p] + 1; while (ch[p][c] == q) ch[p][c] = nq, p = pre[p]; lst = nq; } else { int np = ++node; Max[np] = Max[p] + 1; while (!ch[p][c]) ch[p][c] = np, p = pre[p]; if (ch[p][c] == np) { pre[np] = p; } else { int q = ch[p][c]; if (Max[q] == Max[p] + 1) { pre[np] = q; } else { int nq = ++node; For(i, 0, 25) ch[nq][i] = ch[q][i]; pre[nq] = pre[q]; pre[q] = nq; Max[nq] = Max[p] + 1; while (ch[p][c] == q) ch[p][c] = nq, p = pre[p]; lst = nq; } else { int np = ++node; Max[np] = Max[p] + 1; while (!ch[p][c]) ch[p][c] = np, p = pre[p]; if (ch[p][c] == np) { pre[np] = p; } else { int q = ch[p][c]; if (Max[q] == Max[p] + 1) { pre[np] = q; } else { int nq = ++node; For(i, 0, 25) ch[nq][i] = ch[q][i]; pre[nq] = pre[q]; pre[q] = pre[np] = nq; Max[nq] = Max[p] + 1; while (ch[p][c] == q) ch[p][c] = nq, p = pre[p]; } } lst = np; } } void insert(char *S) { int l = strlen(S); For(i, 0, l - 1) extend(S[i] - 'a'); lst = 0; } vector<int> G[N]; int son[N], sz[N]; void DFS_init(int o) { sz[o] = 1; for (int v : G[o]) { DFS_init(v); sz[o] += sz[v]; if (!son[o] || sz[v] > sz[son[o]]) son[o] = v; } } int top[N]; int id[N], dfn; int top[N]; int id[N], dfn; void DFS_decompose(int o) { if (o) { id[o] = ++dfn; sumc[dfn] = sumc[dfn - 1] + Max[o] - Max[pre[o]]; } top[o] = pre[o] && son[pre[o]] == o ? top[pre[o]] : o; if (son[o]) DFS_decompose(son[o]); for (int v : G[o]) { if (v == son[o]) continue; DFS_decompose(v); } } void init() { For(i, 1, node) G[pre[i]].push_back(i); DFS_init(0); DFS_decompose(0); } int root; void modify(char *S) { int l = strlen(S), o = 0; For(i, 0, l - 1) { o = ch[o][S[i] - 'a']; int p = o; while (p) { T.modify(root, 1, dfn, id[top[p]], id[p]); p = pre[top[p]]; } } printf("%lld\n", T.sqr[root]); } }M; int n; char *S[N], buffer[N]; int main() { scanf("%d", &n); char *p = buffer; For(i, 1, n) { S[i] = p; scanf("%s", p); p += strlen(S[i]) + 1; M.insert(S[i]); } M.init(); For(i, 1, n) M.modify(S[i]); return 0; }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
e <cstdio> #include <cstdlib> #include <assert.h> #include <iostream> #include <algorithm> #include <vector> using namespace std; #define rep(i,a,n) for (int i=a;i<n;i++) #define per(i,a,n) for (int i=n-1;i>=a;i--) #define pb push_back #define mp make_pair #define all(x) (x).begin(),(x).end() #define fi first #define se second #define SZ(x) ((int)(x).size()) typedef vector<int> VI; typedef long long ll; typedef pair<int,int> PII; const ll mod=1000000007; ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;} ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;} // head const int N=101000; int w[N],c[N],n; ll s[N],c0[N],c1[N]; void solve() { rep(i,0,n) scanf("%d",w+i); if (*min_element(w,w+n)>=0) { puts("0"); return; } rep(i,1,n+1) s[i]=s[i-1]+w[i-1]; int k=max_element(s+1,s+n+1)-s; rotate(w,w+k,w+n); rep(i,1,n+1) s[i]=s[i-1]+w[i-1]; ll cnt=0; rep(i,1,n+1) c[i]=0; vector<ll> v; rep(i,1,n) v.pb(s[i]); sort(all(v)); per(i,1,n) { int x=lower_bound(all(v),s[i])-v.begin()+1; for (int y=x-1;y;y-=y&-y) cnt+=c[y]; for (int y=x;y<=n;y+=y&-y) c[y]++; } sort(s+1,s+n); int m=s[n]; if (m<=0) { puts("-1"); return; rep(i,0,m) c0[i]=c1[i]=0; rep(i,1,n) s[i]=-s[i]+m; reverse(s+1,s+n); for (int i=1;i<n;i++) { int j=i; while (j+1<n&&s[j+1]==s[i]) j++; int c=j-i+1; ll v=s[i]; cnt+=(v-1)/m*c; rep(j,0,m) cnt+=c*((v/m-(v%m<j))*c0[j]-c1[j]); v++; c0[v%m]+=c; c1[v%m]+=c*(v/m); i=i+c-1; } printf("%lld\n",cnt); } int main() { // freopen("elasticity.in","r",stdin);freopen("elasticity.out","w",stdout); while (scanf("%d",&n),n!=0) solve(); }
时光花火,水月星辰