[树上莫队] BZOJ 3460 Jc的宿舍

来源:互联网 发布:匡恩网络物联网安全 编辑:程序博客网 时间:2024/05/17 11:36

只要发现这个强制在线是假的就可以离线莫队了

#include<cstdio>#include<cstdlib>#include<algorithm>#include<cmath>using namespace std;typedef long long ll;inline char nc(){  static char buf[100000],*p1=buf,*p2=buf;  return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;}inline void read(int &x){  char c=nc(),b=1;  for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;  for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;}inline void read(char &x){  for (x=nc();!(x>='A' && x<='Z');x=nc());}const int N=200005;struct edge{  int u,v,next;}G[N<<1];int head[N],inum;inline void add(int u,int v,int p){  G[p].u=u; G[p].v=v; G[p].next=head[u]; head[u]=p;}#define V G[p].vconst int K=19;int depth[N],fat[N][K],pre[N],clk;int sta[N],pnt;int B,pos[N],cnt;inline void dfs(int u,int fa){  pre[u]=++clk;  depth[u]=depth[fa]+1; fat[u][0]=fa;  for (int k=1;k<K;k++) fat[u][k]=fat[fat[u][k-1]][k-1];  int last=pnt;  for (int p=head[u];p;p=G[p].next){    if (V==fa) continue;    dfs(V,u);    if (pnt-last>=B){      ++cnt; while (pnt!=last) pos[sta[pnt--]]=cnt;    }  }  sta[++pnt]=u;}inline int LCA(int u,int v){  if (depth[u]<depth[v]) swap(u,v);  for (int k=K-1;~k;k--)    if ((depth[u]-depth[v])>>k&1)      u=fat[u][k];  if (u==v) return u;  for (int k=K-1;~k;k--)    if (fat[u][k]!=fat[v][k])      u=fat[u][k],v=fat[v][k];  return fat[u][0];}int val[N];int sx[N],icnt;inline int Bin(int x){  return lower_bound(sx+1,sx+icnt+1,x)-sx;}ll c1[N],c2[N];inline void add(int x,int r){  for (int i=x;i<=icnt;i+=i&-i) c1[i]+=r*sx[x],c2[i]+=r;}inline ll sum1(int x){  ll ret1=0; for (int i=x;i;i-=i&-i) ret1+=c1[i]; return ret1;}inline ll sum2(int x){  ll ret2=0; for (int i=x;i;i-=i&-i) ret2+=c2[i]; return ret2;}inline ll sum2(int l,int r){  if (l>r) return 0;  return sum2(r)-sum2(l-1);}struct event{  int u,v,idx;  event(int u=0,int v=0,int idx=0):u(u),v(v),idx(idx) { }  bool operator < (const event &B) const{    return pos[u]==pos[B.u]?pre[v]<pre[B.v]:pos[u]<pos[B.u];  }}ev[N<<1];int tot;ll ans=0;int vst[N];inline void Rev(int x){  if (!vst[x]){    ans+=sx[val[x]]+sum1(val[x])+(ll)sx[val[x]]*sum2(val[x]+1,icnt);    add(val[x],1); vst[x]=1;  }else{    add(val[x],-1); vst[x]=0;    ans-=sx[val[x]]+sum1(val[x])+(ll)sx[val[x]]*sum2(val[x]+1,icnt);  }}inline void T(int u,int v){  while (u!=v)    if (depth[u]<depth[v]) Rev(v),v=fat[v][0];    else Rev(u),u=fat[u][0];}ll Ans[N<<1];inline void Solve(){  T(ev[1].u,ev[1].v);  int lca=LCA(ev[1].u,ev[1].v);  Rev(lca);  Ans[ev[1].idx]=ans;  Rev(lca);  for (int i=2;i<=tot;i++){    T(ev[i].u,ev[i-1].u);    T(ev[i].v,ev[i-1].v);    lca=LCA(ev[i].u,ev[i].v);    Rev(lca);    Ans[ev[i].idx]=ans;    Rev(lca);  }}int n,m;int main(){  int key,x; char order;  freopen("t.in","r",stdin);  freopen("t.out","w",stdout);  read(n); read(m); read(key);  for (int i=1;i<=n;i++) read(val[i]),sx[++icnt]=val[i];  sort(sx+1,sx+icnt+1); icnt=unique(sx+1,sx+icnt+1)-sx-1;  for (int i=1;i<=n;i++) val[i]=Bin(val[i]);  for (int i=1;i<=n;i++)    read(x),i>1?(add(i,x,++inum),add(x,i,++inum)):void(0);  B=sqrt(n);  dfs(1,0);  if (pnt) { ++cnt; while (pnt) pos[sta[pnt--]]=cnt; }  int c=1;  for (int i=1;i<=m;i++){    read(order); read(x);    if (order=='C')      c=x;    else{      ev[++tot]=event(c,x%n+1,tot);      ev[++tot]=event(c,(x+key)%n+1,tot);    }  }  sort(ev+1,ev+tot+1);  if (tot) Solve();  int pre=0;  for (int i=1;i<=tot/2;i++)    if (!pre)      printf("%lld\n",Ans[2*i-1]),pre=Ans[2*i-1]&1;    else      printf("%lld\n",Ans[2*i]),pre=Ans[2*i]&1;  return 0;}
0 0
原创粉丝点击