Title effect: a string given sequence, asking the longest substring legitimate long, which must meet the legal substring substring [1, C] is number greater than or equal to K 0
answer:
It is defined as a right end point comprising a point of minimum required range right endpoint
Then initialization can be O (n) calculated at each point a right end point
Defines the minimum interval containing the right end point to a point interval
Different definitions interval when the two leftmost elements of the smallest interval containing interval not simultaneously two different
It is not difficult to think of a legitimate substring, if and only if all the most on the left of different intervals are included in the substring, substring legitimate at this time
Therefore, when there is not difficult to think of an illegal range, the range of this illegal left point as the dividing point, divided into left and right sides recursive operation
So with a divide and conquer approach, start asking substring [1, n] is legitimate, if legal, may be the answer, if not legally, then find all the illegal left point, to divide and conquer as the split point go on
Find illegal left point is the complexity of the bottleneck, we consider it to optimize
Maintenance of a segment tree, the largest segment tree maintenance the right point, and provide the right point point where
Then difficult to think of a time segment tree needs to ask [l, r] to obtain the right to see if the right end point of greater than r, is not greater than legitimate, the value returned by another segment tree is not legal point, which divides the dividing points rule
Taking into account all the same color I just left there with the best, so just put each color leftmost interval when I first joined the tree line, from left to right when strict partition, delete a point to delete point while under color of deleting point of a range of added tree line, so we can guarantee no missing or wrong answers
Because each point will be added and deleted once again, so the time complexity of O (nlogn), this problem can
Code:
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #define INF 1000000007 using namespace std; int n,c,k,tans; int a[100001],nxt[100001],hd[100001]; int minsb[100001]; struct node { int p,minr; }dat[100001*20]; void pushup(int pos) { if(dat[pos<<1].minr>=dat[pos<<1|1].minr)dat[pos]=dat[pos<<1]; else dat[pos]=dat[pos<<1|1]; } void change(int l,int r,int p,int v,int pos) { //printf("%d %d %d\n",l,r,p); if(l==r && l==p) { dat[pos]=(node){p,v}; return; } int mid=l+r>>1; if(p<=mid)change(l,mid,p,v,pos<<1); else change(mid+1,r,p,v,pos<<1|1); pushup(pos); } node ask(int l,int r,int al,int ar,int pos) { if(l==al && r==ar)return dat[pos]; int mid=l+r>>1; node t1,t2; if(ar<=mid)return ask(l,mid,al,ar,pos<<1); if(al>mid)return ask(mid+1,r,al,ar,pos<<1|1); t1=ask(l,mid,al,mid,pos<<1); t2=ask(mid+1,r,mid+1,ar,pos<<1|1); if(t1.minr>=t2.minr)return t1; else return t2; } void work(int l,int r) { //printf("%d %d\n",l,r); if(l>r)return; node td=ask(1,n,l,r,1); //printf(" %d %d\n",td.p,td.minr); if(l==r) { if(td.minr<=r)tans=max(tans,1); change(1,n,l,0,1); if(nxt[l])change(1,n,nxt[l],minsb[nxt[l]],1); return; } if(td.minr>r) { work(l,td.p-1); change(1,n,td.p,0,1); if(nxt[td.p])change(1,n,nxt[td.p],minsb[nxt[td.p]],1); work(td.p+1,r); } else { tans=max(tans,r-l+1); for(int i=l;i<=r;i++) { //printf("*%d* %d\n",i,nxt[i]); change(1,n,i,0,1); //printf("==-=-=-=-=-=-=\n"); if(nxt[i])change(1,n,nxt[i],minsb[nxt[i]],1); } return; } } void init() { memset(a,0,sizeof(a)); memset(nxt,0,sizeof(nxt)); memset(hd,0,sizeof(hd)); memset(minsb,0,sizeof(minsb)); for(int i=1;i<=n;i++)change(1,n,i,0,1); tans=0; } int main() { while(scanf("%d%d%d",&n,&c,&k)!=EOF) { init(); for(int i=1;i<=n;i++)scanf("%d",&a[i]); for(int i=n;i>0;i--) { nxt[i]=hd[a[i]]; hd[a[i]]=i; } for(int i=1;i<=c;i++) { int t=hd[i],l=1,j; if(!t)continue; j=t; while(l<k && j) { j=nxt[j]; if(j)l++; } if((!j) || l<k) { while(t){minsb[t]=INF;t=nxt[t];} } else { while(t && j){minsb[t]=j;j=nxt[j];t=nxt[t];} while(t){minsb[t]=INF;t=nxt[t];} } } for(int i=1;i<=c;i++)if(hd[i])change(1,n,hd[i],minsb[hd[i]],1); work(1,n); printf("%d\n",tans); //for(int i=1;i<=n;i++)printf("%d ",minsb[i]); } return 0; }
心得:考场上很快就想到了区间的做法,但是最后维护线段树时只放最左边的想法一直没有突破导致浪费了一点时间,还需要更加努力啊