It is a relatively new template problem, even if the codeforces on the small C or posted out.
Description
Given a sequence of length n A1~an, each element represents a color. M operations, one of two types per operation:
1 p x: Changes the color of the P position to x;
2 L R: Ask the [l,r] interval for the sum of "maximum occurrence-minimum occurrence" of each color within the interval.
Input
The first line is two positive integers n, m;
The second row n integers, representing a1~an;
Next m lines, each line represents an action shown by a title.
Output
For each operation 2, output the answer to the question.
Sample Input
7 6
1 2 3 1 3 2 1
2 3 7
2 1 3
1 7 2
1 3 2
2 1 6
2 5 7
Sample Output
5
0
7
1
HINT
1≤n,m≤100 000,1≤ai ≤n;
1≤p,x≤n,1≤l≤r≤n.
Solution
It should be said to start the problem is still very easy, no matter what the following is done, we can first determine that it is a data structure problem.
We consider for each element that we maintain the position of the last occurrence of its color.
This seems to be one of the most familiar rectangles to ask a class of questions. Let's compare the number of color types in the Ask interval:
The first dimension represents the interval subscript, and the second dimension represents the position of the last occurrence of the color, and the information to be maintained is the number of occurrences of that position (in fact only 0 and 1), with the purpose of summing.
The same thing seems to be true:
The first dimension represents the interval subscript, the second dimension represents the position of the last occurrence of the color, and the information to be maintained is the difference between the interval subscript and the last occurrence, with the purpose of summing.
This seems to be perfect, we can directly tree set tree ... And then it's not very cool to pass the question because the space is blown up.
So what can we do, we can use our magic divide and conquer algorithm--CDQ Division!
The main idea of the CDQ algorithm is to divide the operating interval into two halves and calculate the effect of the first half of the operation on the latter half of the inquiry.
This would be equivalent to removing the online changes and changing the query offline.
This also requires that the inquiry be CDQ, and that if the operation will affect each other, it will be useless.
For example, an operation is an addition and the query is to take Max, so the query is not satisfied with the merge.
For this problem, the effect of each action on the answer is independent, and each change in color changes up to 6 times the information we maintain:
Set PRE[X] to the location of the last occurrence of the color[x], Suc[x] is the location of the next occurrence of color[x]. And we just need to maintain pre[x].
Suppose to modify Pre[x], after the change of Pre[x] is npre[x],suc[x] the same.
All the information to be modified is: pre[x],pre[suc[x]],pre[nsuc[x]].
For each information on the two-dimensional plane operation is a single point minus and a single point plus, so the total is 3*2=6 times.
Completely converted to offline operation, only ask the rectangle and the query to sort by a common line tree can be done.
Each operation appears in the LOGM division interval, the complexity of a single operation is Logn, so the total time complexity O (MLOGMLOGN).
#include <cstdio>#include<cstring>#include<algorithm>#include<cmath>#include<Set>#definell Long Long#defineMM 264005#defineMN 500005using namespacestd;structmeg{intKi,pos,lf,rf,val,aps;} PX[MN];structnode{intG,x,y;} B[MM];Set<int>Se[mm];ll t[mm],ans[mm];intc[mm][4],las[mm],pre[mm],col[mm];intMq,n,m,pxin;inlineintRead () {intn=0, f=1;CharC=GetChar (); while(c<'0'|| C>'9') {if(c=='-') f=-1; C=GetChar ();} while(c>='0'&& c<='9') {n=n*Ten+c-'0'; C=GetChar ();} returnNF;} InlinevoidGetadd (intXintZ) { for(x+=mq;x;x>>=1) t[x]+=Z;} inline ll Getsum (intXinty) {Register LL Lt=0; for(x+=mq,y+=mq;x<=y;x>>=1, y>>=1) { if(x&1) lt+=t[x++]; if(~y&1) lt+=t[y--]; } returnlt;}BOOLcmpConstmeg& A,Constmeg& b) {returnA.pos<b.pos | | A.pos==b.pos && a.ki<b.ki;}voidsolve () {sort (px+1, px+pxin+1, CMP); Registerinti; for(i=1; i<=pxin;++i)if(px[i].ki==0) {if(PX[I].LF) Getadd (px[i].lf,px[i].val);} ElseAns[px[i].aps]+=getsum (PX[I].LF,PX[I].RF) *Px[i].val; for(i=1; i<=pxin;++i)if(px[i].ki==0&&PX[I].LF) Getadd (px[i].lf,-px[i].val);}voidWorkintLintRintGS) { if(!gs| | L==R)return; inti,qet=0,mid=l+r>>1; Pxin=0; for(i=l;i<=mid;++i)if(b[i].g==1) {px[++pxin]= (MEG) {0, b[i].x,c[i][0],0, c[i][0]-b[i].x,0}; px[++pxin]= (MEG) {0, b[i].x,c[i][1],0, b[i].x-c[i][1],0}; px[++pxin]= (MEG) {0, c[i][2],b[i].x,0, b[i].x-c[i][2],0}; px[++pxin]= (MEG) {0, c[i][2],c[i][0],0, c[i][2]-c[i][0],0}; px[++pxin]= (MEG) {0, c[i][3],c[i][1],0, c[i][1]-c[i][3],0}; px[++pxin]= (MEG) {0, c[i][3],b[i].x,0, c[i][3]-b[i].x,0}; } for(i=mid+1; i<=r;++i)if(b[i].g==2) {px[++pxin]= (MEG) {1, b[i].x-1, b[i].x,b[i].y,-1, i}; px[++pxin]= (MEG) {1, B[i].y, B[i].x,b[i].y,1, i}; ++Qet; } solve (); Work (L,mid,gs-qet); Work (mid+1, R,qet);}intMain () {registerinti,x,qet=0; N=read (); m=read (); Pxin=0; for(mq=1; mq<n; mq<<=1); --MQ; for(i=1; i<=n;++i) {Col[i]=x=read (); Las[i]=PRE[X]; pre[x]=i; Se[x].insert (i); px[++pxin]= (MEG) {0, I,las[i],0, I-las[i],0}; } for(i=1; i<=m;++i) {b[i].g=read (); B[i].x=read (); b[i].y=read (); if(b[i].g==1) { Set<int>:: Iterator K; K=Se[col[b[i].x]].lower_bound (b[i].x); if(K!=se[col[b[i].x]].begin ())--k,c[i][0]=*k,++k;Elsec[i][0]=0; if((++k)!=se[col[b[i].x]].end ()) c[i][2]=*k;Elsec[i][2]=0; Se[col[b[i].x]].erase (--k); Col[b[i].x]=b[i].y; K=Se[col[b[i].x]].lower_bound (b[i].x); if(K!=se[col[b[i].x]].end ()) c[i][3]=*k;Elsec[i][3]=0; if(K!=se[col[b[i].x]].begin ()) c[i][1]=* (--K);Elsec[i][1]=0; Se[col[b[i].x]].insert (b[i].x); } Else{px[++pxin]= (MEG) {1, b[i].x-1, b[i].x,b[i].y,-1, i}; px[++pxin]= (MEG) {1, B[i].y, B[i].x,b[i].y,1, i}; ++Qet; }} solve (); Work (1, M,qet); for(i=1; i<=m;++i)if(b[i].g==2) printf ("%i64d\n", Ans[i]);}
Last Word
Feeling the problem is disgusting. Only the set insert delete operation.
Compared to tree sets tree, only need to use ordinary line segment tree or more pleasing.
[codeforces]849e Goodbye Souvenir