2019.7.13 義烏模擬賽 T4 sequence
阿新 • • 發佈:2021-07-14
我們考慮對詢問差分,設\(f(l1,r1,l2,r2)\)為左端點在\([l1,r1]\)中,右端點在\([l2,r2]\)中的答案。
那麼一個詢問就變成\(f(1,r,1,r)-f(1,l-1,1,l-1)-f(1,l-1,l,r)\)
前面那個十分平凡,我們考慮後面那個。
將詢問離線,然後就變成每次加入一個點並更新,求答案的東西。
我們預處理出每個點最近的同色點\(las_i\),那麼\([las_i+1,i]\)區間內的點答案奇偶性都會變化。
然後還要每次將一個輔助陣列\(B\)加上每一位對應的奇偶性。
這個東西懶標記隨便維護。再維護一個區間反轉後的tag即可。
時間複雜度\(O(nlogn)\)
code:
#include<bits/stdc++.h> #define I inline #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((a)<(b)?(a):(b)) #define abs(x) ((x)>0?(x):-(x)) #define re register #define ll long long #define db double #define N 500000 #define M 500000 #define mod 1000000007 #define eps (1e-7) #define U unsigned int #define it iterator #define Gc() getchar() #define Me(x,y) memset(x,y,sizeof(x)) using namespace std; int n,m,x,y,A[N+5],tot,pus,las[N+5],F[N+5<<2],Sum[N+5<<2];ll Ans[N+5],H[N+5]; struct ques{int l,r,flag,id;}tmp;vector<ques> Q[N+5]; I void push(int l,int r,int now){F[now]^=1;Sum[now]=r-l+1-Sum[now];} I void pushF(int l,int r,int now){if(!F[now]) return;int m=l+r>>1;push(l,m,now<<1);push(m+1,r,now<<1|1);F[now]=0;} I void Up(int now){Sum[now]=Sum[now<<1]+Sum[now<<1|1];} I void get(int x,int y,int l=1,int r=n,int now=1){ if(x<=l&&r<=y) return (void)(F[now]^=1,Sum[now]=r-l+1-Sum[now]);pushF(l,r,now);int m=l+r>>1; x<=m&&(get(x,y,l,m,now<<1),0);y>m&&(get(x,y,m+1,r,now<<1|1),0);Up(now); } I int find(int x,int y,int l=1,int r=n,int now=1){ if(x<=l&&r<=y) return Sum[now];int m=l+r>>1,ans=0;pushF(l,r,now);x<=m&&(ans+=find(x,y,l,m,now<<1));y>m&&(ans+=find(x,y,m+1,r,now<<1|1));return ans; } struct TrieTree{ ll Ans[N+5<<2],Sum[N+5<<2],F[N+5<<2],H1[N+5<<2],H2[N+5<<2]; I void Up(int now){Sum[now]=Sum[now<<1]+Sum[now<<1|1];Ans[now]=Ans[now<<1]+Ans[now<<1|1];} I void pushF(int now,int siz){swap(H1[now],H2[now]);F[now]^=1;Sum[now]=siz-Sum[now];} I void pushf(int l,int r,int now){int m=l+r>>1;F[now]&&(pushF(now<<1,m-l+1),pushF(now<<1|1,r-m),F[now]=0);} I void pushH1(int l,int r,int now,int w){H1[now]+=w;Ans[now]+=Sum[now]*w;} I void pushH2(int l,int r,int now,int w){H2[now]+=w;Ans[now]+=(r-l+1-Sum[now])*w;} I void pushh(int l,int r,int now){int m=l+r>>1;H1[now]&&(pushH1(l,m,now<<1,H1[now]),pushH1(m+1,r,now<<1|1,H1[now]),H1[now]=0);H2[now]&&(pushH2(l,m,now<<1,H2[now]),pushH2(m+1,r,now<<1|1,H2[now]),H2[now]=0);} I void getF(int x,int y,int l=1,int r=n,int now=1){ if(x<=l&&r<=y) return pushF(now,r-l+1);int m=l+r>>1;pushf(l,r,now);pushh(l,r,now); x<=m&&(getF(x,y,l,m,now<<1),0);y>m&&(getF(x,y,m+1,r,now<<1|1),0);Up(now); } I void getH(int x,int y,int l=1,int r=n,int now=1){ if(x<=l&&r<=y) return pushH1(l,r,now,1);int m=l+r>>1;pushf(l,r,now);pushh(l,r,now); x<=m&&(getH(x,y,l,m,now<<1),0);y>m&&(getH(x,y,m+1,r,now<<1|1),0);Up(now); } I ll find(int x,int y,int l=1,int r=n,int now=1){ if(x<=l&&r<=y) return Ans[now];int m=l+r>>1;ll ans=0;pushf(l,r,now);pushh(l,r,now); x<=m&&(ans+=find(x,y,l,m,now<<1));y>m&&(ans+=find(x,y,m+1,r,now<<1|1));return ans; } }S; int main(){ freopen("sequence.in","r",stdin);freopen("sequence.out","w",stdout); re int i,j;scanf("%d",&n);for(i=1;i<=n;i++) scanf("%d",&A[i]);for(i=1;i<=n;i++) las[i]=H[A[i]],H[A[i]]=i; Me(H,0);for(i=1;i<=n;i++)get(las[i]+1,i),H[i]=H[i-1]+find(1,i);scanf("%d",&m); for(i=1;i<=m;i++)scanf("%d%d",&x,&y),Ans[i]=H[y]-H[x-1],x^1&&(Q[x-1].push_back((ques){1,x-1,1,i}),Q[y].push_back((ques){1,x-1,-1,i}),0); for(i=1;i<=n;i++){ S.getF(las[i]+1,i);S.getH(1,i);for(j=0;j<Q[i].size();j++) tmp=Q[i][j],Ans[tmp.id]+=tmp.flag*S.find(tmp.l,tmp.r); }for(i=1;i<=m;i++) printf("%lld\n",Ans[i]); }