• 【刷题】BZOJ 1036 [ZJOI2008]树的统计Count


    Description

      一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成
    一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 I
    II. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身

    Input

      输入的第一行为一个整数n,表示节点的个数。接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有
    一条边相连。接下来n行,每行一个整数,第i行的整数wi表示节点i的权值。接下来1行,为一个整数q,表示操作
    的总数。接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。
    对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。

    Output

      对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。

    Sample Input

    4
    1 2
    2 3
    4 1
    4 2 1 3
    12
    QMAX 3 4
    QMAX 3 3
    QMAX 3 2
    QMAX 2 3
    QSUM 3 4
    QSUM 2 1
    CHANGE 1 5
    QMAX 3 4
    CHANGE 3 6
    QMAX 3 4
    QMAX 2 4
    QSUM 3 4

    Sample Output

    4
    1
    2
    2
    10
    6
    5
    6
    5
    16

    Solution

    这题还是很水的
    只要维护链上的信息,又是静态,没有加删边
    所以LCT和树剖都可以做

    这是LCT的代码:(自带大常数)

    #include<bits/stdc++.h>
    #define ui unsigned int
    #define ll long long
    #define db double
    #define ld long double
    #define ull unsigned long long
    const int MAXN=30000+10,inf=0x3f3f3f3f;
    int n,q;
    #define lc(x) ch[(x)][0]
    #define rc(x) ch[(x)][1]
    struct LCT{
    	int ch[MAXN][2],fa[MAXN],rev[MAXN],val[MAXN],Mx[MAXN],Sm[MAXN],stack[MAXN],cnt;
    	inline void init()
    	{
    		memset(Mx,-inf,sizeof(Mx));
    		memset(val,-inf,sizeof(val));
    	}
    	inline bool nroot(int x)
    	{
    		return lc(fa[x])==x||rc(fa[x])==x;
    	}
    	inline void reverse(int x)
    	{
    		std::swap(lc(x),rc(x));
    		rev[x]^=1;
    	}
    	inline void pushup(int x)
    	{
    		Sm[x]=(val[x]!=-inf?val[x]:0)+Sm[lc(x)]+Sm[rc(x)];
    		Mx[x]=val[x];
    		if(Mx[lc(x)]>Mx[x])Mx[x]=Mx[lc(x)];
    		if(Mx[rc(x)]>Mx[x])Mx[x]=Mx[rc(x)];
    	}
    	inline void pushdown(int x)
    	{
    		if(rev[x])
    		{
    			if(lc(x))reverse(lc(x));
    			if(rc(x))reverse(rc(x));
    			rev[x]=0;
    		}
    	}
    	inline void rotate(int x)
    	{
    		int f=fa[x],p=fa[f],c=(rc(f)==x);
    		if(nroot(f))ch[p][rc(p)==f]=x;
    		fa[ch[f][c]=ch[x][c^1]]=f;
    		fa[ch[x][c^1]=f]=x;
    		fa[x]=p;
    		pushup(f);
    		pushup(x);
    	}
    	inline void splay(int x)
    	{
    		cnt=0;
    		stack[++cnt]=x;
    		for(register int i=x;nroot(i);i=fa[i])stack[++cnt]=fa[i];
    		while(cnt)pushdown(stack[cnt--]);
    		for(register int y=fa[x];nroot(x);rotate(x),y=fa[x])
    			if(nroot(y))rotate((lc(y)==x)==(lc(fa[y])==y)?y:x);
    		pushup(x);
    	}
    	inline void access(int x)
    	{
    		for(register int y=0;x;x=fa[y=x])splay(x),rc(x)=y,pushup(x);
    	}
    	inline void makeroot(int x)
    	{
    		access(x);splay(x);reverse(x);
    	}
    	inline void split(int x,int y)
    	{
    		makeroot(x);access(y);splay(y);
    	}
    	inline void link(int x,int y)
    	{
    		makeroot(x);fa[x]=y;
    	}
    };
    LCT T;
    #undef lc
    #undef rc
    template<typename T> inline void read(T &x)
    {
    	T data=0,w=1;
    	char ch=0;
    	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    	if(ch=='-')w=-1,ch=getchar();
    	while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
    	x=data*w;
    }
    template<typename T> inline void write(T x,char c='')
    {
    	if(x<0)putchar('-'),x=-x;
    	if(x>9)write(x/10);
    	putchar(x%10+'0');
    	if(c!='')putchar(c);
    }
    template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
    template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
    template<typename T> inline T min(T x,T y){return x<y?x:y;}
    template<typename T> inline T max(T x,T y){return x>y?x:y;}
    int main()
    {
    	read(n);
    	T.init();
    	for(register int i=1;i<n;++i)
    	{
    		int u,v;
    		read(u);read(v);
    		T.link(u,v);
    	}
    	for(register int i=1;i<=n;++i)T.access(i),T.splay(i),read(T.val[i]),T.pushup(i);
    	read(q);
    	while(q--)
    	{
    		char opt[8];int u,v;
    		scanf("%s",opt);read(u);read(v);
    		if(!strcmp(opt,"QMAX"))T.split(u,v),write(T.Mx[v],'
    ');
    		if(!strcmp(opt,"QSUM"))T.split(u,v),write(T.Sm[v],'
    ');
    		if(!strcmp(opt,"CHANGE"))T.access(u),T.splay(u),T.val[u]=v,T.pushup(u);
    	}
    	return 0;
    }
    

    这是树剖的代码(老代码,以前的):

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define Mid ((l+r)>>1)
    #define lson rt<<1,l,Mid
    #define rson rt<<1|1,Mid+1,r
    const ll MAXN=30000+10;
    ll n,m,Mod,to[MAXN<<1],nex[MAXN<<1],beg[MAXN],fa[MAXN],Tre[MAXN],Val[MAXN],size[MAXN],Sum[MAXN<<2],Add[MAXN<<2],sta[MAXN],end[MAXN],hson[MAXN],cnt,e,dep[MAXN],top[MAXN],Max[MAXN<<2];
    inline void read(ll &x)
    {
        ll data=0,w=1;
        char ch=0;
        while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
        if(ch=='-')w=-1,ch=getchar();
        while(ch>='0'&&ch<='9')data=(data<<3)+(data<<1)+(ch^'0'),ch=getchar();
        x=data*w;
    }
    inline void insert(ll x,ll y)
    {
        to[++e]=y;
        nex[e]=beg[x];
        beg[x]=e;
    }
    inline void dfs1(ll x,ll f)
    {
        ll tmp=0;
        fa[x]=f;
        size[x]=1;
        dep[x]=dep[f]+1;
        for(register ll i=beg[x];i;i=nex[i])
            if(to[i]==f)continue;
            else
            {
                dfs1(to[i],x);
                size[x]+=size[to[i]];
                if(size[to[i]]>tmp)tmp=size[to[i]],hson[x]=to[i];
            }
    }
    inline void dfs2(ll x,ll head)
    {
        top[x]=head;
        sta[x]=++cnt;
        Val[cnt]=Tre[x];
        if(hson[x])dfs2(hson[x],head);
        for(register ll i=beg[x];i;i=nex[i])
            if(to[i]==fa[x]||to[i]==hson[x])continue;
            else dfs2(to[i],to[i]);
        end[x]=cnt;
    }
    inline void PushUp(ll rt)
    {
        Sum[rt]=Sum[rt<<1]+Sum[rt<<1|1];
        Max[rt]=max(Max[rt<<1],Max[rt<<1|1]);
    }
    inline void PushDown(ll rt,ll len)
    {
        Add[rt<<1]+=Add[rt];
        Add[rt<<1|1]+=Add[rt];
        Max[rt<<1]+=Add[rt];
        Max[rt<<1|1]+=Add[rt];
        Sum[rt<<1]+=Add[rt]*(len-(len>>1));
        Sum[rt<<1|1]+=Add[rt]*(len>>1);
        Add[rt]=0;
    }
    inline void Build(ll rt,ll l,ll r)
    {
        if(l==r)Sum[rt]=Val[l],Max[rt]=Val[l];
        else
        {
            Build(lson);
            Build(rson);
            PushUp(rt);
        }
    }
    inline void init()
    {
        dfs1(1,0);
        dfs2(1,1);
        Build(1,1,n);
    }
    inline void Update(ll rt,ll l,ll r,ll pos,ll k)
    {
        if(l==r&&r==pos)
        {
            Max[rt]=k;
            Sum[rt]=k;
        }
        else
        {
            if(Add[rt])PushDown(rt,r-l+1);
            if(pos<=Mid)Update(lson,pos,k);
            else if(pos>Mid)Update(rson,pos,k);
            PushUp(rt);
        }
    }
    inline ll Query(ll rt,ll l,ll r,ll L,ll R)
    {
        if(L<=l&&r<=R)return Sum[rt];
        else
        {
            if(Add[rt])PushDown(rt,r-l+1);
            ll tmp=0;
            if(L<=Mid)tmp+=Query(lson,L,R);
            if(R>Mid)tmp+=Query(rson,L,R);
            return tmp;
        }
    }
    inline ll Maxfind(ll rt,ll l,ll r,ll L,ll R)
    {
        if(L<=l&&r<=R)return Max[rt];
        else
        {
            if(Add[rt])PushDown(rt,r-l+1);
            ll tmp=-1e18;
            if(L<=Mid)tmp=max(tmp,Maxfind(lson,L,R));
            if(R>Mid)tmp=max(tmp,Maxfind(rson,L,R));
            return tmp;
        }
    }
    inline ll Getmax(ll x,ll y)
    {
        ll res=-1e18;
        while(top[x]!=top[y])
            if(dep[top[x]]>dep[top[y]])
            {
                res=max(Maxfind(1,1,n,sta[top[x]],sta[x]),res);
                x=fa[top[x]];
            }
            else
            {
                res=max(Maxfind(1,1,n,sta[top[y]],sta[y]),res);
                y=fa[top[y]];
            }
        res=max(res,Maxfind(1,1,n,min(sta[x],sta[y]),max(sta[x],sta[y])));
        return res;
    }
    inline ll Getans(ll x,ll y)
    {
        ll res=0;
        while(top[x]!=top[y])
            if(dep[top[x]]>dep[top[y]])
            {
                res+=Query(1,1,n,sta[top[x]],sta[x]);
                x=fa[top[x]];
            }
            else
            {
                res+=Query(1,1,n,sta[top[y]],sta[y]);
                y=fa[top[y]];
            }
        res+=Query(1,1,n,min(sta[x],sta[y]),max(sta[x],sta[y]));
        return res;
    }
    int main()
    {
        read(n);
        for(register ll i=1;i<n;++i)
        {
            ll u,v;
            read(u);read(v);
            insert(u,v);insert(v,u);
        }
        for(register ll i=1;i<=n;++i)read(Tre[i]);
        init();
        read(m);
        while(m--)
        {
            char str[10];
            scanf("%s",str);
            if(!strcmp(str,"QMAX"))
            {
                ll x,y;
                read(x);read(y);
                printf("%lld
    ",Getmax(x,y));
            }
            else if(!strcmp(str,"QSUM"))
            {
                ll x,y;
                read(x);read(y);
                printf("%lld
    ",Getans(x,y));
            }
            else if(!strcmp(str,"CHANGE"))
            {
                ll x,t;
                read(x);read(t);
                Update(1,1,n,sta[x],t);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    Nginx(ab性能测试)
    Nginx(配置域名后,不能配置到public目录原因)
    sublime text3的php代码合法检查
    Nginx(expires 缓存减轻服务端压力)
    Nginx(Gzip加速访问速度)
    Nginx(Rewrite语法)
    Nginx(location分析)
    Nginx(日志切割)
    Nginx(Logs)
    Java内部类——闭包与回调
  • 原文地址:https://www.cnblogs.com/hongyj/p/8759674.html
Copyright © 2020-2023  润新知