bzoj 4129 Haruna’s Breakfast 树上莫队

按照dfs序分块,莫队乱搞

再套个权值分块

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#define N 100005
using namespace std;
 
int e=1,head[N];
struct edge{
    int u,v,next;
}ed[2*N];
void add(int u,int v){
    ed[e].u=u; ed[e].v=v;
    ed[e].next=head[u];
    head[u]=e++;
}
 
int qq,cc,n,m,nn,nnn,be[N],bb[N],gy[N],dep[N],fa[N],anc[N][18];
bool vis[N];
int num[N],all[N],ll[N],rr[N];
struct Query{
    int l,r,id,tim,ans;
}qr[N];
void add_query(int x,int y){
    qr[++qq].l=x;
    qr[qq].r=y;
    qr[qq].id=qq;
    qr[qq].tim=cc;
}
bool cmp1(Query a,Query b){
    if(be[a.l]==be[b.l])
        return be[a.r]<be[b.r];
    return be[a.l]<be[b.l];
}
bool cmp2(Query a,Query b){
    return a.id<b.id;
}
 
struct Change{
    int pos,nxt,pre;
}ch[N];
void add_change(int x,int y){
    ch[++cc].pos=x;
    ch[cc].nxt=y;
    ch[cc].pre=gy[x];
    gy[x]=y;
}
 
int stack[N],top=0,cnt;
void dfs(int x){
    dep[x]=dep[fa[x]]+1;
    for(int i=1;i<=15;i++)
        anc[x][i]=anc[anc[x][i-1]][i-1];
    for(int i=head[x];i;i=ed[i].next){
        int v=ed[i].v;
        if(v==fa[x]) continue;
        fa[v]=anc[v][0]=x;
        dfs(v);
        if(top>=nn){
            ++cnt;
            while(top) 
              be[stack[top--]]=cnt;
        }
    }
    stack[++top]=x;
    if(x==1&&top){
        ++cnt;
        while(top)
          be[stack[top--]]=cnt;
    }
}
int lca(int x,int y)
{
    if(dep[x]<dep[y])swap(x,y);//dep[x]>=dep[y]
    for(int i=15;~i;i--)
        if(dep[anc[x][i]]>=dep[y])
            x=anc[x][i];
    if(x==y) return x;
    for(int i=15;~i;i--)
        if(anc[x][i]!=anc[y][i]){
            x=anc[x][i];
            y=anc[y][i];
        }
    return anc[x][0];
}
void pls(int x){
    vis[x]=1;
    if(gy[x]>n+1) return;
    if(++num[gy[x]]==1)
        all[bb[gy[x]]]++;
}
void reduc(int x){
    vis[x]=0;
    if(gy[x]>n) return;
    if(--num[gy[x]]==0)
        all[bb[gy[x]]]--;
}
void update(int x){
    if(vis[x]){
        reduc(x);
        return ;
    }
    if(!vis[x]) pls(x);
}
void change(int x,int y){
    int now=lca(x,y);
    //printf("x==%d  y==%d  now==%d\n",x,y,now);
    while(x!=now)
        update(x),x=fa[x];
    while(y!=now)
        update(y),y=fa[y];
}
 
int main()
{
    scanf("%d%d",&n,&m);
    nn=(int)pow(n,2.0/3.0);
    nnn=(int)sqrt(n);
    for(int i=1;i<=n;i++){
        scanf("%d",&gy[i]);
        bb[i]=i/nnn+1;
    }
    bb[0]=1;
    for(int i=1;i<=bb[n];i++){
        ll[i]=(i-1)*nnn;
        rr[i]=i*nnn-1;
    }
    int u,v;
    for(int i=1;i<n;i++){
        scanf("%d%d",&u,&v);
        add(u,v); add(v,u);
    }
    dfs(1);
    int opt,a,b;
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&opt,&a,&b);
        if(opt==0) add_change(a,b);
        if(opt==1) add_query(a,b);
    }
    sort(qr+1,qr+qq+1,cmp1);
    int l=1,r=1,t=cc,old,now;
    update(1);
    for(int i=1;i<=qq;i++)
    {
        //printf("%d    %d    %d    %d\n",qr[i].id,qr[i].tim,qr[i].l,qr[i].r);
        old=lca(l,r);
        now=lca(qr[i].l,qr[i].r);
        change(qr[i].l,l);
        change(qr[i].r,r);
        update(old); update(now);
        for(int j=t+1;j<=qr[i].tim;j++){
            if(dep[ch[j].pos]>=dep[now]&&(lca(ch[j].pos,qr[i].l)==ch[j].pos||lca(ch[j].pos,qr[i].r)==ch[j].pos)){
                update(ch[j].pos); gy[ch[j].pos]=ch[j].nxt; update(ch[j].pos);
            }
            gy[ch[j].pos]=ch[j].nxt;
        }
        for(int j=t;j>qr[i].tim;j--){
            if(dep[ch[j].pos]>=dep[now]&&(lca(ch[j].pos,qr[i].l)==ch[j].pos||lca(ch[j].pos,qr[i].r)==ch[j].pos)){
                update(ch[j].pos); gy[ch[j].pos]=ch[j].pre; update(ch[j].pos);
            }
            gy[ch[j].pos]=ch[j].pre;
        }
        t=qr[i].tim; l=qr[i].l; r=qr[i].r;
        for(int j=1;j<=bb[n];j++)
            if(all[j]!=rr[j]-ll[j]+1){
                for(int k=ll[j];k<=rr[j];k++){
                    if(!num[k]){
                        qr[i].ans=k;
                        break;
                    }
                }
                break;
            }
        //for(int j=0;j<=n;j++) printf("k==%d  num==%d\n",j,num[j]);
        //printf("ans================%d\n",qr[i].ans);
    }
    sort(qr+1,qr+qq+1,cmp2);
    for(int i=1;i<=qq;i++)
        printf("%d\n",qr[i].ans);
    return 0;
}


posted @ 2017-07-27 12:15  Ren_Ivan  阅读(140)  评论(0编辑  收藏  举报