Title Link: Http://codeforces.com/contest/981/problem/G
Main topic:
There are n initial empty ' magical ' re-sets, adding elements to a ' re-set ', if the element is not present, adding it, otherwise the number of all elements in the re-centralization will be doubled.
For example, adding $2$ to ${1,3}$ will get ${1,2,3}$, adding $2$ to ${1,2,3,3}$ will get ${1,1,2,2,3,3,3,3}$.
$Q $ operations, each action either adds an element to all the re-sets within a range, or asks for the sum of the size of the re-set within a range.
$n, q≤2x10^5$
The following:
It is found that the interval is the interval multiplication for the occurrence of the element, and the interval plus
Operation 1 We first put the $[l,r]$ all multiply 2, and then have already appeared before the current element of the interval multiplied by 2 of the inverse of +1, and finally merge the left and right interval. Merging is probably the key to ensuring the complexity of the operation, but I don't know how to count it.
found that we want to maintain the interval of each element, while supporting a convenient merge, we open n set is OK
That's what I found out I didn't even write the interval multiplication line tree
#include <algorithm>#include<cstring>#include<cstdio>#include<iostream>#include<Set>#definePA pair<int,int>#defineMid ((l+r) >>1)using namespaceStd;typedefLong Longll;Const intn=2e5+ the;Const intMod=998244353; ll N,q,inv;ll sum[n<<2],add[n<<2],mul[n<<2];Set<pa>St[n]; inline ll read () {CharCh=GetChar (); ll S=0, f=1; while(ch<'0'|| Ch>'9') {if(ch=='-') f=-1; ch=GetChar ();} while(ch>='0'&&ch<='9') {s= (s<<3) + (s<<1) +ch-'0'; ch=GetChar ();} returns*F;} ll Qpow (ll A,ll b) {ll re=1; for(; b;b>>=1, A=a*a%mod)if(b&1) re=re*a%MoD; returnre;}voidBuildintOintLintR) {Mul[o]=1; add[o]=sum[o]=0; if(L==R)return; Build (o<<1, L,mid); Build (o<<1|1, mid+1, R);}voidPushup (intOintLintR) { //sum[o]=sum[o<<1]+sum[o<<1|1];Sum[o]= (sum[o<<1]*mul[o<<1]+add[o<<1]* (mid-l+1))%MoD; Sum[o]= (sum[o]+sum[o<<1|1]*mul[o<<1|1]+add[o<<1|1]* (r-mid))%MoD;}voidPushdown (intOintLintR) { if(mul[o]!=1) {ll P=Mul[o]; Mul[o]=1; //(sum[o<<1]*=p)%=mod; //(sum[o<<1|1]*=p)%=mod;(add[o<<1]*=P)%=MoD; (Add[o<<1|1]*=P)%=MoD; (Mul[o<<1]*=P)%=MoD; (Mul[o<<1|1]*=P)%=MoD; } if(add[o]!=0) {ll P=Add[o]; Add[o]=0; //(sum[o<<1]+=p* (mid-l+1))%=mod; //(sum[o<<1|1]+=p* (r-mid))%=mod;(add[o<<1]+=P)%=MoD; (Add[o<<1|1]+=P)%=MoD; }}voidUpdateintOintLintRintXintY,ll Z,intflag) { if(l>=x&&r<=y) {if(flag==1) {(Mul[o]*=Z)%=MoD; (Add[o]*=Z)%=MoD; //(sum[o]*=z)%=mod; } if(flag==2) {(Add[o]+=Z)%=MoD; //(sum[o]+= (r-l+1) *z)%=mod; } return; } pushdown (O,l,r); if(x<=mid) Update (o<<1, L,mid,x,y,z,flag); if(y>mid) Update (o<<1|1, mid+1, R,x,y,z,flag); Pushup (o,l,r);} voidMergeintXintLintR) { Set<pa>:: Iterator it; It=St[x].lower_bound (PA (l,l)); for(; It!=st[x].end (); it++) { Set<pa>::iterator lst=it;lst--; intL= (*lst). second+1; intR= (*it). first-1; intUpl=Max (l,l); intUpr=min (r,r); if(upr>=UPL) {Update (1,1, N,UPL,UPR,INV,1); Update (1,1, N,UPL,UPR,1,2); } if((*it). First>=r) Break; } intMergel=l,merger=R; It=st[x].upper_bound (PA (l,l)); it--; if((*it). Second>=mergel) mergel= (*it). First; It=st[x].upper_bound (PA (r,r)); it--; if((*it). Second>=merger) merger= (*it). Second; Vector<pa>er; It=St[x].lower_bound (PA (Mergel,mergel)); for(; It!=st[x].end (); it++) {PA e=*it; if(e.first>=mergel&&e.second<=merger) Er.push_back (e); Else Break; } for(intI=0; I<er.size (); i++) St[x].erase (Er[i]); St[x].insert (PA (Mergel,merger));} ll query (intOintLintRintXinty) { if(l>=x&&r<=y)return(Sum[o]*mul[o]+add[o]* (r-l+1))%MoD;//if (l>=x&&r<=y) return sum[o]%mod;pushdown (O,L,R); ll re=0; if(X<=mid) (Re+=query (o<<1, l,mid,x,y))%=MoD; if(Y>mid) (Re+=query (o<<1|1, mid+1, r,x,y))%=MoD; Pushup (O,L,R); returnre;}intMain () {INV=qpow (2, mod-2); //inv= (mod+1)/2;N=read (); q=read (); for(intI=0; i<=n;i++) {St[i].insert (PA (0,0)); St[i].insert (PA (n+1, n+1)); } Build (1,1, N); while(q--) { intopt=read (); if(opt==1) { intL=read (), R=read (), z=read (); Update (1,1, N,l,r,2,1); Merge (Z,l,r); } if(opt==2) { intL=read (), r=read (); printf ("%lld\n", Query (1,1, N,l,r)); } } return 0;}
[Avito Code Challenge 2018 G] Magic multisets (segment tree)