【Bzoj3531】旅行

題意:有n個城市,每個城市有權值和顏色,支持的操作有單點修改權值,單點修改顏色,查詢區間同顏色之和,查詢區間同顏色最大值。


思路:對於每種顏色,放入不同的線段樹,但其實整個加起來還是還是n個結點,值得注意的是,這裏要使用動態開點,要一步步記錄左右兒子的編號,而不能使用2i,2i+1直接去找,而這樣建樹的話,就可以很方便的查詢同顏色的結點了,修改操作啥的把原顏色中的結點改爲0,再在現在的顏色中開點就可以了。


#include <cstdio>
#include <algorithm>

#define Rep(i,s,t) for(int i=s;i<=t;i++)
#define For(i,s,t) for(int i=s;i;i=t)

using namespace std;

const int maxx = 100000 + 25;
const int maxm = 4000000 + 25;
const int Inf = (unsigned)(-1) >> 1;

int head[maxx],nxt[maxx<<1],to[maxx<<1],a[maxx],c[maxx];
int top[maxx],rnk[maxx],size[maxx],dpt[maxx],ftr[maxx],son[maxx];
int T[maxm],Tmax[maxm],lc[maxm],rc[maxm],rt[maxx];

int num,cnt,tot,n,m,x,y,k;
char f[8];

namespace Y{

    void Ins(int x,int y) {to[++num]=y;nxt[num]=head[x];head[x]=num;}    
    
    void Dfs1(int x){
        size[x] = 1;
        For( i , head[x] , nxt[i] ){
            int now = to[i];if(now == ftr[x]) continue;
            dpt[now] = dpt[x] + 1;ftr[now] = x;
            Dfs1(now);size[x] += size[now];
            if(size[now] > size[son[x]]) son[x] = now;
        }
    }
    
    void Dfs2(int x,int brn){
        rnk[x] = ++cnt;top[x] = brn;
        if(son[x]) Dfs2(son[x],brn);
        For( i , head[x] , nxt[i] )
            if(to[i] != ftr[x] && to[i] != son[x])
                Dfs2(to[i],to[i]);
    }
    
    void upt(int i){
        T[i] = T[lc[i]] + T[rc[i]];
        Tmax[i] = max(Tmax[lc[i]],Tmax[rc[i]]);
    }
    
    void modify(int &i,int pos,int l,int r,int k){
        if(!i) i = ++tot;if(l == r) {T[i] = Tmax[i] = k;return;}
        int mid = (l+r) >> 1;
        if(pos <= mid) modify(lc[i],pos,l,mid,k);
        if(pos >  mid) modify(rc[i],pos,mid+1,r,k);
        upt(i);
    }
    
    void chk(int &tmp,int pls,int flag){
        if(flag == 0) tmp = tmp + pls;
        if(flag == 1) tmp = max(tmp,pls);
    }
    
    int Query(int i,int x,int y,int l,int r,int flag){
        if(x <= l && r <= y) return flag? Tmax[i] : T[i];
        int ans = (flag)? -Inf : 0;int mid = (l+r) >> 1;
        if(x <= mid) chk(ans,Query(lc[i],x,y,l,mid,flag),flag);
        if(y >  mid) chk(ans,Query(rc[i],x,y,mid+1,r,flag),flag);
        return ans;
    }
    
    int Get(int i,int x,int y,int flag){
        int ans = (flag)? -Inf : 0;
        while(top[x] != top[y]){
            if(dpt[top[x]] > dpt[top[y]]) x^=y^=x^=y;
            chk(ans,Query(i,rnk[top[y]],rnk[y],1,n,flag),flag);
            y = ftr[top[y]];
        }
        if(rnk[x] > rnk[y]) x^=y^=x^=y;
        chk(ans,Query(i,rnk[x],rnk[y],1,n,flag),flag);
        return ans;
    }
    
}

using namespace Y;

int main(){
    scanf("%d%d",&n,&m);
    Rep( i , 1 , n ) scanf("%d%d",&a[i],&c[i]);
    Rep( i , 1 , n-1 ) scanf("%d%d",&x,&y),Ins(x,y),Ins(y,x);
    Dfs1(1),Dfs2(1,1);Rep( i , 1 , n ) modify(rt[c[i]],rnk[i],1,n,a[i]);
    while( m-- ){
        scanf("%s",f);
        if(f[1] == 'S') scanf("%d%d",&x,&y),printf("%d\n",Get(rt[c[x]],x,y,0));
        if(f[1] == 'C'){ 
            scanf("%d%d",&x,&y);
            modify(rt[c[x]],rnk[x],1,n,0);
            c[x]=y;
            modify(rt[c[x]],rnk[x],1,n,a[x]);
        }
        if(f[1] == 'W')
            scanf("%d%d",&x,&y),a[x]=y,modify(rt[c[x]],rnk[x],1,n,a[x]);
        if(f[1] == 'M') scanf("%d%d",&x,&y),printf("%d\n",Get(rt[c[x]],x,y,1));
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章