莫队算法

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;

  long long  lm,rm;
  long long c[50001],a[50001];
  long long t1,t2;
  long long ans;
  
  struct data{
      long long  l,r,key1,num;
  }q[50001];
  
  struct str{
      long long s,m;
  }an[50001];

  bool comp(const data &a, const data &b){
      if (a.key1<b.key1) return(1);
      if (a.key1>b.key1) return(0);
      if (a.r<b.r) return(1);
      return(0);
  }
  
  long long gcd(long long a,long long b){
      if (a%b==0) return(b);else return(gcd(b,a%b));
  }
  
  void movel(long long targ){
      if (lm<targ)
        for (;lm<targ;){
          ans=ans-c[a[lm]]*(c[a[lm]]-1)+(c[a[lm]]-1)*(c[a[lm]]-2);
          c[a[lm]]--;
          lm++;
          }
        
    if (lm>targ)
      for (;lm>targ;){
          lm--;
          ans=ans-c[a[lm]]*(c[a[lm]]-1)+c[a[lm]]*(c[a[lm]]+1);
          c[a[lm]]++;
      }  
  }
  
  void mover(long long  targ){
      if (rm<targ)
      for (;rm<targ;){
          rm++;
          ans=ans-c[a[rm]]*(c[a[rm]]-1)+(c[a[rm]]+1)*c[a[rm]];
          c[a[rm]]++;
      }
      
    if (rm>targ)
    for (;rm>targ;){
        ans=ans-c[a[rm]]*(c[a[rm]]-1)+(c[a[rm]]-1)*(c[a[rm]]-2);
        c[a[rm]]--;
        rm--;
    }  
  }
  
  int main(){
       
    long long n,m;
    scanf("%lld%lld",&n,&m);
    int siz=int(sqrt(n));
    
    for (long long i=1;i<=n;i++) scanf("%lld",&a[i]);
    for (long long i=1;i<=m;i++) {
        scanf("%lld%lld",&q[i].l,&q[i].r);
        q[i].key1=q[i].l/siz;
        q[i].num=i;
    }      
    
    sort(q+1,q+m+1,comp);
    
    lm=1,rm=0;
    ans=0;    
     for (long long i=1;i<=m;i++){
        movel(q[i].l);mover(q[i].r);
        t1=ans;t2=(rm-lm+1)*(rm-lm);
        if (t1!=0){
        long long gc=gcd(t1,t2);
        an[q[i].num].s=t1/gc;an[q[i].num].m=t2/gc;
        } else {
            an[q[i].num].s=0;an[q[i].num].m=1;
        }
    }
    
    for (int i=1;i<=m;i++) printf("%lld/%lld\n",an[i].s,an[i].m);
  }

BZOJ2038 小Z的袜子

_________________________________________________________

带修改莫队与树上莫队

Codechef FEB17 DISTNUM3

#include <bits/stdc++.h>
using namespace std;
  
  int brac[500001][2],lis[500001],cnt,nd[500001],nxt[1000001],des[1000001];
  int dep[500001],fa[500001][21],n,Q,ta[500001],a[500001],opt[500001][3];
  int pre[500001],app[500001],ans,PO,L,R,inq[500001],blo,quecnt,fin[500001];
  int scnt,getnxt[500001],getpre[500001];
  
  struct data{
      int num,orityp,ori;
  }tmp[500001];
  
  int mycomp(const data&a,const data&b){
      return(a.num<b.num);
  }
  
  struct ques{
      int pos,l,r,ori;
  }que[500001];
  
  int mycomp2(const ques&a,const ques&b){
      if (a.pos/blo<b.pos/blo) return(1);
      if (a.pos/blo>b.pos/blo) return(0);
    if (a.l/blo<b.l/blo) return(1);
      if (a.l/blo>b.l/blo) return(0);
      return(a.r<b.r);
  }
  
  void addedge(int x,int y){
      nxt[++scnt]=nd[x];des[scnt]=y;nd[x]=scnt;
  }
  
  void dfs(int po,int f=-1){
      brac[po][0]=++cnt;
      lis[cnt]=po;
      for(int p=nd[po];p!=-1;p=nxt[p])
        if (des[p]!=f){
            dep[des[p]]=dep[po]+1;
            fa[des[p]][0]=po;
            dfs(des[p],po);
      }
    brac[po][1]=++cnt;
    lis[cnt]=po;
  }
  
  void initlca(){
      for (int i=1;i<=20;i++)
        for (int j=1;j<=n;j++)
          fa[j][i]=fa[fa[j][i-1]][i-1];
  }
  
  void initpre(){
      memcpy(ta,a,sizeof(a));
      for (int i=1;i<=Q;i++)
        if (opt[i][0]==2){
          pre[i]=ta[opt[i][1]];
          ta[opt[i][1]]=opt[i][2];
      }
  }
   
  void edi(int po,int num){
      app[po]+=num;
      if (app[po]==1&&num==1) ans++;
      if (app[po]==0&&num==-1) ans--;
  } 
   
  void moverPO(){
    PO=getnxt[PO];
    if (opt[PO][0]==2){
      edi(a[opt[PO][1]],(-1)*inq[opt[PO][1]]);
      a[opt[PO][1]]=opt[PO][2];
      edi(a[opt[PO][1]],1*inq[opt[PO][1]]);
    }
  } 
   
  void movelPO(){
      if (opt[PO][0]==2){
      edi(a[opt[PO][1]],(-1)*inq[opt[PO][1]]);
      a[opt[PO][1]]=pre[PO];
      edi(a[opt[PO][1]],1*inq[opt[PO][1]]);            
    }
    PO=getpre[PO];
  } 
  
  void moverR(){
      R++;
      inq[lis[R]]^=1;
      edi(a[lis[R]],(inq[lis[R]] ? 1:-1));
  }
  
  void movelR(){
      inq[lis[R]]^=1;
      edi(a[lis[R]],(inq[lis[R]] ? 1:-1));
      R--;
  }
  
  void moverL(){
      inq[lis[L]]^=1;
      edi(a[lis[L]],(inq[lis[L]] ? 1:-1));
      L++;
  }
  
  void movelL(){
      L--;
      inq[lis[L]]^=1;
      edi(a[lis[L]],(inq[lis[L]] ? 1:-1));
  }
   
  int getlca(int x,int y){
      if (dep[x]<dep[y]) swap(x,y);
    for (int i=20;i>=0;i--)
      if (dep[fa[x][i]]>=dep[y]) 
        x=fa[x][i];
    for (int i=20;i>=0;i--)
      if (fa[x][i]!=fa[y][i])
        x=fa[x][i],y=fa[y][i];
    if (x==y) return(x);else return(fa[x][0]);
  }  
   
  void initlink(){
      int lst=0;
      for (int i=1;i<=Q;i++)
        if (opt[i][0]==2){
          getpre[i]=lst;
          lst=i;
      }
    getpre[Q+1]=lst;
    lst=Q+1;
    for (int i=Q;i>=1;i--)
      if (opt[i][0]==2){
          getnxt[i]=lst;
          lst=i;
      }
    getnxt[0]=lst;
  } 
   
  int main(){      
      scanf("%d%d",&n,&Q);
      for (int i=1;i<=n;i++) nd[i]=-1;
      for (int i=1;i<=n;i++){
        cnt++;
      tmp[cnt].orityp=1;tmp[cnt].ori=i;
      scanf("%d",&tmp[cnt].num);    
    }
      for (int i=1;i<n;i++){
        int t1,t2;
        scanf("%d%d",&t1,&t2);
      addedge(t1,t2);addedge(t2,t1);    
    }
      for (int i=1;i<=Q;i++){
        scanf("%d%d%d",&opt[i][0],&opt[i][1],&opt[i][2]);
        if (opt[i][0]==2){
          cnt++;
        tmp[cnt].orityp=2;tmp[cnt].ori=i;
        tmp[cnt].num=opt[i][2];    
      }
    }
      
      sort(tmp+1,tmp+cnt+1,mycomp);
      int p=0;tmp[0].num=-1e9;
      for (int i=1;i<=cnt;i++){
        if (tmp[i].num!=tmp[i-1].num) p++;
        if (tmp[i].orityp==1) a[tmp[i].ori]=p;else
          opt[tmp[i].ori][2]=p;
    }
    
    cnt=0;dep[1]=1;
    dfs(1);
    initlca();initpre();
    initlink();
    
    blo=pow(4*n,2.0/3);
    for (int i=1;i<=Q;i++)
      if (opt[i][0]==1){
          if (brac[opt[i][1]][0]>brac[opt[i][2]][0])
            swap(opt[i][1],opt[i][2]);
          quecnt++;
          if (brac[opt[i][1]][1]>brac[opt[i][2]][0])
            que[quecnt].l=brac[opt[i][1]][0],
            que[quecnt].r=brac[opt[i][2]][0];else
            que[quecnt].l=brac[opt[i][1]][1],
            que[quecnt].r=brac[opt[i][2]][0];
          que[quecnt].pos=i;
          que[quecnt].ori=i;
      }
    sort(que+1,que+quecnt+1,mycomp2);
    
    L=1;R=0;PO=0;
    for (int i=1;i<=quecnt;i++){
      while (getnxt[PO]<que[i].pos) moverPO();
      while (PO>que[i].pos) movelPO();
      while (R<que[i].r) moverR();
      while (R>que[i].r) movelR();
      while (L<que[i].l) moverL();
      while (L>que[i].l) movelL();

      fin[que[i].ori]=ans;
      int lc=getlca(opt[que[i].ori][1],opt[que[i].ori][2]);
      if ((lc!=opt[que[i].ori][1])&&(lc!=opt[que[i].ori][2]))
        if (!app[a[lc]])
          fin[que[i].ori]++;
    }
    
    for (int i=1;i<=Q;i++)
      if (opt[i][0]==1) 
        printf("%d\n",fin[i]);
  }

 

posted @ 2016-05-25 13:37  z1j1n1  阅读(212)  评论(0编辑  收藏  举报