zoukankan      html  css  js  c++  java
  • 树链剖分模板-2716-【ZJOI2008】树的统计

    题目

        一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。
      我们将以下面的形式来要求你对这棵树完成一些操作:
      I.CHANGE u t : 把结点u的权值改为t
      II.QMAX u v: 询问从点u到点v的路径上的节点的最大权值
      III.QSUM u v: 询问从点u到点v的路径上的节点的权值和
      注意:从点u到点v的路径上的节点包括u和v本身
      
      输入文件的第一行为一个整数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之间。
      
    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
    
    
    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #define maxn 100005
    using namespace std;
    int n,m;
    int val[maxn],num[maxn],siz[maxn],ch[maxn][3],fa[maxn],maxx[maxn],sum[maxn],flag[maxn],cnt,root;
    void pushup(int x)
    {
    	siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+num[x];
    	maxx[x]=val[x];
    	if(ch[x][0]) maxx[x]=max(maxx[x],maxx[ch[x][0]]);
    	if(ch[x][1]) maxx[x]=max(maxx[x],maxx[ch[x][1]]);
    }
    void pushdown(int x)
    {
    	if(!x) return;
    	if(flag[x])
    	{
    		if(ch[x][0]){flag[ch[x][0]]^=1; swap(ch[ch[x][0]][0],ch[ch[x][0]][1]);}
    		if(ch[x][1]){flag[ch[x][1]]^=1; swap(ch[ch[x][1]][0],ch[ch[x][1]][1]);}
    		flag[x]=0;
    	}
    	if(sum[x])
    	{
    		if(ch[x][0]) sum[ch[x][0]]+=sum[x],val[ch[x][0]]+=sum[x],maxx[ch[x][0]]+=sum[x];
    		if(ch[x][1]) sum[ch[x][1]]+=sum[x],val[ch[x][1]]+=sum[x],maxx[ch[x][1]]+=sum[x];
    		sum[x]=0;
    	}
    }
    void table()
    {
    	ch[1][1]=n+2; fa[n+2]=1;
    	val[1]=0; val[n+2]=0;
    	num[1]=num[n+2]=1; siz[1]=2; siz[n+2]=1;
    	cnt=1; root=1;
    }
    void rot(int x,int &f)
    {
    	int y=fa[x],z=fa[y],l=(ch[y][0]!=x),r=(l^1);
    	if(y==f) f=x;
    	else ch[z][ch[z][1]==y]=x;
    	fa[x]=z; fa[y]=x; fa[ch[x][r]]=y;
    	ch[y][l]=ch[x][r]; ch[x][r]=y;
    	pushup(y); pushup(x);
    }
    void splay(int x,int &f)
    {
    	while(x!=f)
    	{
    		int y=fa[x],z=fa[y];
    		pushdown(z); pushdown(y); pushdown(x);
    		if(y!=f){if(ch[z][0]==y^ch[y][0]==x) rot(x,f);else rot(y,f);}
    		rot(x,f);
    	}
    }
    int findk(int x,int rt)
    {
    	if(!x)return 0;
    	pushdown(rt);int temp;
    	if(siz[ch[rt][0]]+num[rt]>=x&&siz[ch[rt][0]]<x) temp=rt;
    	else if(siz[ch[rt][0]]>=x) temp=findk(x,ch[rt][0]);
    	else temp=findk(x-siz[ch[rt][0]]-num[rt],ch[rt][1]);
    	pushup(rt);
    	return temp;
    }
    int main()
    {
    	scanf("%d%d",&n,&m); table();
    	for(int i=1;i<=n;++i)
    	{
    		int a=findk(i,root),b=findk(i+1,root);
    		splay(a,root); splay(b,ch[a][1]);
    		ch[b][0]=++cnt; num[cnt]=siz[cnt]=1; fa[cnt]=b;
    		pushup(cnt); pushup(b); pushup(a);
    	}
    	cnt=n+2;
    	while(m--)
    	{
    		int f1,f2,f3,f4; scanf("%d",&f1);
    		if(f1==1)
    		{
    			scanf("%d%d%d",&f2,&f3,&f4);
    			int a=findk(f2,root),b=findk(f3+2,root);
    			splay(a,root); splay(b,ch[a][1]);
    			sum[ch[b][0]]+=f4; val[ch[b][0]]+=f4; maxx[ch[b][0]]+=f4;
    			pushup(b); pushup(a);
    	
    		}
    		else if(f1==2)
    		{
    			scanf("%d%d",&f2,&f3);int a=findk(f2,root),b=findk(f3+2,root);
    			splay(a,root); splay(b,ch[a][1]);
    			flag[ch[b][0]]^=1;
    			swap(ch[ch[b][0]][0],ch[ch[b][0]][1]);
    		}
    		else if(f1==3)
    		{
    			scanf("%d%d",&f2,&f3);int a=findk(f2,root),b=findk(f3+2,root);
    			splay(a,root); splay(b,ch[a][1]);
    			printf("%d
    ",maxx[ch[b][0]]);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    Python冒泡排序(4)
    Python冒泡排序(3)
    Python3默认递归最大深度是998
    Python利用递归函数和列表推导式实现快速排序
    天池比赛的文章--欢迎大家交流
    caffe学习笔记1
    网络压缩系列1:低秩逼近
    yolov1
    Windows下用Caffe跑自己的数据(遥感影像)
    基于灰度共生矩阵的纹理提取
  • 原文地址:https://www.cnblogs.com/wuwendongxi/p/13159520.html
Copyright © 2011-2022 走看看