首页 > 其他分享 >HAOI 2015 树上操作

HAOI 2015 树上操作

时间:2023-05-14 15:13:25浏览次数:38  
标签:HAOI ch pw fw read 100000 qrw 2015 树上

有一棵点数为 N 的树,以点 1 为根,且树有点权。然后有 M 个操作,分为三种:

  • 操作 1 :把某个节点 x 的点权增加 a 。
  • 操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。
  • 操作 3 :询问某个节点 x 到根的路径中所有点的点权和。

做法:树链剖分+线段树,板子题

#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cctype>
typedef long long LL;
typedef unsigned long long ULL;
namespace FastIo{
    typedef __uint128_t L;
    static char buf[100000],*p1=buf,*p2=buf,fw[100000],*pw=fw;
    #define gc p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++
    inline void pc(const char &ch){
    	if(pw-fw==100000)fwrite(fw,1,100000,stdout),pw=fw;
    	*pw++=ch;
	}
    #define fsh fwrite(fw,1,pw-fw,stdout),pw=fw
	struct FastMod{
        FastMod(ULL b):b(b),m(ULL((L(1)<<64)/b)){}
        ULL reduce(ULL a){
            ULL q=(ULL)((L(m)*a)>>64);
            ULL r=a-q*b;
            return r>=b?r-b:r;
        }
        ULL b,m;
    }HPOP(10);
    struct QIO{
    	char ch;
    	int st[40];
		bool pd;
		template<class T>inline void read(T &x){
    		x=0,ch=gc,pd=false;
    		while(!isdigit(ch)){pd=ch=='-'?true:false;ch=gc;}
    		while(isdigit(ch)){x=(x<<3)+(x<<1)+(ch^48);ch=gc;}
    		if(pd)x=-x;
		}
		template<class T>inline void write(T a){
			if(a<0)a=-a,pc('-');
			do{st[++st[0]]=HPOP.reduce(a);a/=10;}while(a);
			while(st[0])pc(st[st[0]--]^48);
			pc('\n');
		}
	}qrw;
}
using namespace FastIo;
#include<algorithm>
#define NUMBER1 100000
#define P(A) A=-~A
#define mid (l+r>>1)
#define ls(a) a<<1
#define rs(a) a<<1|1
#define sz (r-l+1)
#define lson l,mid,ls(rt)
#define rson mid+1,r,rs(rt)
#define fione(begin,end) for(register int i=begin;i<=end;P(i))
#define tt for(register int i=head[u];~i;i=e[i].next)
struct EDGE{int next,to;}e[(NUMBER1<<2)+5];
int head[NUMBER1+5],tot(0),n,a[NUMBER1+5],b[NUMBER1+5],fa[NUMBER1+5],size[NUMBER1+5],depth[NUMBER1+5],top[NUMBER1+5],son[NUMBER1+5],id[NUMBER1+5],cnt(0);
struct Segment{
	inline void push_up(const int &rt){tree[rt]=tree[(ls(rt))]+tree[rs(rt)];}
	inline void change(int l,int r,int rt,LL date){tree[rt]+=(LL)date*sz,lazy[rt]+=date;}
	inline void push_down(int l,int r,int rt){
		change(lson,lazy[rt]);
		change(rson,lazy[rt]);
		lazy[rt]=0;
	}
	void build(int l,int r,int rt){
		if(l==r)return tree[rt]=b[l],void();
		build(lson);build(rson);
		push_up(rt);
	}
	LL intervalsum(int l,int r,int rt,int x,int y){
		if(x<=l&&r<=y)return tree[rt];
		push_down(l,r,rt);
		LL res(0);
		if(x<=mid)res+=intervalsum(lson,x,y);
		if(mid<y)res+=intervalsum(rson,x,y);
		return res;
	}
	void intervaland(int l,int r,int rt,int x,int y,LL date){
		if(x<=l&&r<=y)return tree[rt]+=(LL)sz*date,lazy[rt]+=date,void();
		push_down(l,r,rt);
		if(x<=mid)intervaland(lson,x,y,date);
		if(mid<y)intervaland(rson,x,y,date);
		push_up(rt);
	}
	void pointand(int l,int r,int rt,int p,int date){
		if(l==r)return tree[rt]+=date,void();
		push_down(l,r,rt);
		if(p<=mid)pointand(lson,p,date);
		else pointand(rson,p,date);
		push_up(rt);
	}
	LL tree[(NUMBER1<<2)+5],lazy[(NUMBER1<<2)+5];
}seg;
inline void add(const int &u,const int &v){e[++tot].next=head[u];head[u]=tot,e[tot].to=v;}
void dfs1(int u,int fath,int deep){
	depth[u]=deep,fa[u]=fath,size[u]=1;
	int ms(-1);
	tt{
		if(e[i].to==fath)continue;
		dfs1(e[i].to,u,deep+1);
		size[u]+=size[e[i].to];
		if(size[e[i].to]>ms)ms=size[e[i].to],son[u]=e[i].to;
	}
}
void dfs2(int u,int tf){
	id[u]=++cnt;
	b[cnt]=a[u],top[u]=tf;
	if(!son[u])return;
	dfs2(son[u],tf);
	tt{
		if(e[i].to==fa[u]||e[i].to==son[u])continue;
		dfs2(e[i].to,e[i].to);
	}
}
inline LL treesum(int x,int y){
	LL ans(0);
	while(top[x]!=top[y]){
		if(depth[top[x]]<depth[top[y]])std::swap(x,y);
		ans+=seg.intervalsum(1,n,1,id[top[x]],id[x]);
		x=fa[top[x]];
	}
	if(depth[x]>depth[y])std::swap(x,y);
	ans+=seg.intervalsum(1,n,1,id[x],id[y]);
	return ans;
}
signed main(){
	memset(head,-1,sizeof(head));
	int m,k,x,y;
	qrw.read(n);
	qrw.read(m);
	fione(1,n)qrw.read(a[i]);
	fione(1,n-1){
		qrw.read(x);qrw.read(y);
		add(x,y);add(y,x);;
	}
	dfs1(1,0,1);
	dfs2(1,1);
	seg.build(1,n,1);
	while(m--){
		qrw.read(k);
		qrw.read(x);
		switch(k){
			case 1:
				qrw.read(y);
				seg.pointand(1,n,1,id[x],y);
				break;
			case 2:
				qrw.read(y);
				seg.intervaland(1,n,1,id[x],id[x]+size[x]-1,y);
				break;
			case 3:qrw.write(treesum(x,1));break;
		}
	}
	fsh;
    exit(0);
    return 0;
}

标签:HAOI,ch,pw,fw,read,100000,qrw,2015,树上
From: https://www.cnblogs.com/SHOJYS/p/17399335.html

相关文章

  • [HAOI2018] 字串覆盖
    [HAOI2018]字串覆盖题目描述小C对字符串颇有研究,他觉得传统的字符串匹配太无聊了,于是他想到了这样一个问题.对于两个长度为n的串A,B,小C每次会给出给出4个参数s,t,l,r.令A从s到t的子串(从1开始标号)为T,令B从l到r的子串为P.然后他会进行下面的操作:如果T的某个子串与P相......
  • [NOIP2015 普及组] 金币
    [NOIP2015普及组]金币题目背景NOIP2015普及组T1题目描述国王将金币作为工资,发放给忠诚的骑士。第一天,骑士收到一枚金币;之后两天(第二天和第三天),每天收到两枚金币;之后三天(第四、五、六天),每天收到三枚金币;之后四天(第七、八、九、十天),每天收到四枚金币……;这种工资发放模式会......
  • 洛谷 P3321 [SDOI2015] 序列统计
    洛谷传送门感觉挺综合的一道题。考虑朴素dp,\(\forallx\inS,f_{i+1,jx\bmodm}\getsf_{i,j}\)。复杂度\(O(nm^2)\)。显然可以矩乘优化至\(O(m^3\logn)\),但是不能通过。如果转移式中是加法而不是乘法,那很容易卷积优化。接下来是一个很重要的套路:化乘为加。实数......
  • luogu P3345 [ZJOI2015]幻想乡战略游戏
    P3345[ZJOI2015]幻想乡战略游戏这道题还是比较有意思的,做了一个比较长的时间,但是点分树实在是太毒瘤了,所以记录一下线段树的做法。题面给一棵树,有边权,每次修改一个点的点权,修改完后输出所有点到这棵树的带权重心的贡献,即\(\sumdis_i\timesval_i\)题解考虑朴素的暴......
  • [Event] Linux con Japan 2015
    日本每年都举办一次LinuxCon,下面是今年的Event及对应的ppthttp://events.linuxfoundation.jp/events/linuxcon-japan粗粗看了一下,竟然还有这么一个主题。HowChinainvolvedinOpenSourceMovement不过幻灯片让人大跌眼镜,讲演怎么样姑且不论,这内容也太少了。http://eve......
  • 「ZJOI2015」地震后的幻想乡
    「ZJOI2015」地震后的幻想乡题意:给定一张图,每条边的边权在\([0,1]\)中随机,求最小生成树的最大边权的期望。其中这个很重要:对于\(n\)个\([0,1]\)之间的随机变量,第\(k\)小的那个的期望值是\(\frac{k}{n+1}\)那暴力就很容易了,假设我们已经按边权从小到大排好了序,也就是相......
  • 树上组合计数
    主要来讲一讲树上的一些有关排列组合计数的问题。树上拓扑序给定一棵包含\(n\)个节点,以\(1\)为根的树。求树上拓扑序个数,即求有多少种排列方式,满足每个节点的父亲排在他前面。\(1\len\le10^6\)显然,如果没有任何限制,整棵树的方案数为\(n!\)。对于一棵以\(x\)为节点......
  • 2023-05-03:给你一棵 二叉树 的根节点 root ,树中有 n 个节点 每个节点都可以被分配一个
    2023-05-03:给你一棵二叉树的根节点root,树中有n个节点每个节点都可以被分配一个从1到n且互不相同的值另给你一个长度为m的数组queries你必须在树上执行m个独立的查询,其中第i个查询你需要执行以下操作:从树中移除以queries[i]的值作为根节点的子树题目所用测试......
  • 2023-05-03:给你一棵 二叉树 的根节点 root ,树中有 n 个节点 每个节点都可以被分配一个
    2023-05-03:给你一棵二叉树的根节点root,树中有n个节点每个节点都可以被分配一个从1到n且互不相同的值另给你一个长度为m的数组queries你必须在树上执行m个独立的查询,其中第i个查询你需要执行以下操作:从树中移除以queries[i]的值作为根节点的子树题目所......
  • P3592 [POI2015] MYJ
    题目描述有\(n\)家洗车店从左往右排成一排,每家店都有一个正整数价格\(p_i\)。有\(m\)个人要来消费,第\(i\)个人会驶过第\(a_i\)个开始一直到第\(b_i\)个洗车店,且会选择这些店中最便宜的一个进行一次消费。但是如果这个最便宜的价格大于\(c_i\),那么这个人就不洗车了。......