zoukankan      html  css  js  c++  java
  • BZOJ1036 [ZJOI2008]树的统计Count

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。

    本文作者:ljh2000
    作者博客:http://www.cnblogs.com/ljh2000-jump/
    转载请注明出处,侵权必究,保留最终解释权!

    题目链接:BZOJ1036

    正解:LCT

    解题报告:

      LCT裸题,连link和cut都不用了…

      每次直接换根然后access一下,查询子树max和sum即可。

    //It is made by ljh2000
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    #include <ctime>
    #include <vector>
    #include <queue>
    #include <map>
    #include <set>
    #include <string>
    #include <complex>
    using namespace std;
    typedef long long LL;
    typedef long double LB;
    typedef complex<double> C;
    const double pi = acos(-1);
    const int MAXN = 30011;
    const int MAXM = 60011;
    int n,q,father[MAXN],tr[MAXN][2],mx[MAXN],sum[MAXN];
    int tag[MAXN],top,stack[MAXN],a[MAXN],ecnt,first[MAXN],to[MAXM],next[MAXM];
    char ch[12];
    inline bool isroot(int x){ return (tr[father[x]][0]!=x) && (tr[father[x]][1]!=x); }
    inline void upd(int x,int y){ if(mx[x]<mx[y]) mx[x]=mx[y];}
    inline int getint(){
        int w=0,q=0; char c=getchar(); while((c<'0'||c>'9') && c!='-') c=getchar();
        if(c=='-') q=1,c=getchar(); while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w;
    }
    
    inline void update(int x){
    	mx[x]=sum[x]=a[x]; int l=tr[x][0],r=tr[x][1];
    	if(l) upd(x,l),sum[x]+=sum[l];
    	if(r) upd(x,r),sum[x]+=sum[r];
    }
    
    inline void pushdown(int x){
    	if(tag[x]==0) return ;
    	int l=tr[x][0],r=tr[x][1];
    	tag[x]=0; tag[l]^=1; tag[r]^=1;
    	swap(tr[x][0],tr[x][1]);
    }
    
    inline void rotate(int x){
    	int y,z; y=father[x]; z=father[y];
    	int l,r; l=(tr[y][1]==x); r=l^1;
    	if(!isroot(y)) tr[z][(tr[z][1]==y)]=x;
    	father[x]=z; father[y]=x;
    	tr[y][l]=tr[x][r]; father[tr[x][r]]=y; tr[x][r]=y;
    	update(y); update(x);
    }
    
    inline void splay(int x){
    	top=0; stack[++top]=x; int y,z;
    	for(int i=x;!isroot(i);i=father[i]) stack[++top]=father[i];
    	for(int i=top;i>=1;i--) pushdown(stack[i]);
    	while(!isroot(x)) {
    		y=father[x]; z=father[y];
    		if(!isroot(y)) {
    			if((tr[y][0]==x) ^ (tr[z][0]==y)) rotate(x);
    			else rotate(y);
    		}
    		rotate(x);
    	}
    }
    
    inline void access(int x){
    	int last=0;
    	while(x) {
    		splay(x); tr[x][1]=last;
    		update(x);//!!!
    		last=x; x=father[x];
    	}
    }
    
    inline void move_to_the_root(int x){
    	access(x);
    	splay(x);
    	tag[x]^=1;
    }
    
    inline void dfs(int x,int fa){
    	for(int i=first[x];i;i=next[i]) {
    		int v=to[i]; if(v==fa) continue;
    		father[v]=x;
    		dfs(v,x);
    	}
    }
    
    inline void work(){
    	n=getint(); int x,y;
    	for(int i=1;i<n;i++) {
    		x=getint(); y=getint();
    		next[++ecnt]=first[x]; first[x]=ecnt; to[ecnt]=y;
    		next[++ecnt]=first[y]; first[y]=ecnt; to[ecnt]=x;
    	}
    	for(int i=1;i<=n;i++) a[i]=getint(),mx[i]=sum[i]=a[i];
    	dfs(1,0);
    	q=getint();
    	while(q--) {
    		scanf("%s",ch); x=getint(); y=getint();
    		if(ch[0]=='C') {
    			splay(x);
    			a[x]=y;
    			update(x);
    		}
    		else if(ch[1]=='S') {
    			move_to_the_root(x);
    			access(y); splay(y);
    			printf("%d
    ",sum[y]);
    		}
    		else {
    			move_to_the_root(x);
    			access(y); splay(y);
    			printf("%d
    ",mx[y]);
    		}
    	}
    }
    
    int main()
    {
        work();
        return 0;
    }
    

      

  • 相关阅读:
    SQL中使用WITH AS提高性能
    电子邮件原理
    DirectoryEntry 活动目录的使用
    Entity Framework 教程(转)
    用sp_addlinkedserver建立链接服务器(sql server2008中通过测试)
    SQL2008和SQL2000可以跨服务器连接查询的测试实例
    Linq快速入门——扩展方法
    easyui 很好很强大
    【转】Jmeter内存溢出处理方式记录
    【转】Jmeter安装成功后的目录介绍
  • 原文地址:https://www.cnblogs.com/ljh2000-jump/p/6478248.html
Copyright © 2011-2022 走看看