Link:
A:
由于每个颜色只染色一次就确定了所有要染色的区间
要求染色的次数其实就是求区间最多嵌套多少层,如果有区间相交则无解
以上操作明显可以将左端点排序后用栈来维护
#include <bits/stdc++.h> using namespace std; #define X first #define Y second #define pb push_back typedef double db; typedef long long ll; typedef pair<int,int> P; const int MAXN=2e5+10; struct node{int x,d,col;}; node dat[MAXN];int st[MAXN],top; int n,x,l[MAXN],r[MAXN],cur,res,tot; bool cmp(node a,node b){return a.x==b.x?a.d<b.d:a.x<b.x;} int main() { scanf("%d",&n); memset(l,0x3f,sizeof(l)); for(int i=1;i<=n;i++) { scanf("%d",&x); l[x]=min(l[x],i),r[x]=max(r[x],i); if(!x) dat[++tot]=node{i,0,0}; } for(int i=1;i<=n;i++) if(r[i]) dat[++tot]=node{l[i],0,i},dat[++tot]=node{r[i],1,i}; sort(dat+1,dat+tot+1,cmp); for(int i=1;i<=tot;i++) {//注意0代表没有颜色要特殊处理 if(!dat[i].col) { if(top) return puts("-1"),0; else continue; } if(!dat[i].d) st[++top]=dat[i].col,cur++; else { if(dat[i].col!=st[top]) return puts("-1"),0; top--;cur--; } res=max(res,cur); } printf("%d",res); return 0; }
注意零代表没有颜色要特殊处理……
B:
涉及字符串匹配想到哈希,结果一开始写成了$O(n^3*log(n))$
由于最外层的字符串长度的可行性是单调的,二分后可优化为$O(n^2*log(n)^2)$
但上述的复杂度是可以继续优化的
使用$two pointers$来利用单调性,每次可行就移动左端点,否则移动右端点
这样可以只检验$2*n$个字符串,复杂度降到了$O(2*n^2*log(n))$
同时该题也可以每次暴力构造$Trie$树来进行匹配,复杂度为$O(n^3)$
#include <bits/stdc++.h> using namespace std; #define X first #define RG register #define Y second #define pb push_back typedef double db; typedef long long ll; typedef pair<int,int> P; typedef unsigned long long ull; const int MAXN=1e3+10,base=233; ull hs[MAXN][MAXN],pre[MAXN]; int n,m,f;char s[MAXN]; map<ull,int> mp; bool check(int x) { for(int i=x;i<=m;i++) { mp.clear();f=1; for(RG int k=1;k<=n;k++) mp[hs[k][i]-hs[k][i-x]*pre[x]]=1; for(RG int k=n+1;k<=2*n;k++) if(mp[hs[k][i]-hs[k][i-x]*pre[x]]){f=0;break;} if(f) return true; } return false; } int main() { scanf("%d%d",&n,&m); pre[0]=1; for(RG int i=1;i<=m;i++) pre[i]=pre[i-1]*base; for(RG int i=1;i<=2*n;i++) { scanf("%s",s+1); for(RG int j=1;j<=m;j++) hs[i][j]=hs[i][j-1]*base+(s[j]-'A'); } int l=1,r=m; while(l<=r) { int mid=(l+r)>>1; if(check(mid)) r=mid-1; else l=mid+1; } printf("%d",l); return 0; }
$two pointers$对比二分的优越之处就在于其能更及时的纠错
如果当前长度不行就直接加长,而二分则要将该长度的所有字符串都检验过再进行调整