萌新求助,不知错在何处,肯请各位巨佬帮忙看下
查看原帖
萌新求助,不知错在何处,肯请各位巨佬帮忙看下
222051
厦门饮冰楼主2020/10/26 23:05
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <bitset>
#include <queue>
#include <functional>
#include <time.h>
#include <math.h>
#include <map>
using namespace std;
#define ll long long
#define ull unsigned long long
const ll N = 4e6+5,M=4e6+5;
const ll logN=20;
const ll Maxl = 1E18 + 10;
const ll memMax = 0x3f;
ll res;
ll sign;
char c;
inline ll readi() {
    sign = 1;
    while (!isdigit(c=getchar()))
        if (c == '-')
            sign = -1;
        else if (c == EOF)
            return -1;
    res = c - '0';
    while (isdigit(c=getchar())) res = res * 10 + (c - '0');
    return res * sign;
}
inline char readc() {
    while ((c = getchar()) == 13 || c == 32 || c == 10)
        ;
    return c;
}

struct way{	//Kur的存边方式不同 
	ll to,nxt;
}w[N*2+10];	//树 

ll head[N+5],idx,val[N+5],fa[N+5],son[N+5],dep[N+5],size[N+5],seg[N+5],rev[N+5],top[N+5];
ll n,m,type,x,y;
ll sum[N*4],tip[N*4];	//4倍 
void addlist(ll a,ll b){
	idx++;
	w[idx].nxt=head[a];
	w[idx].to=b;
	head[a]=idx;
}
void dfs1(ll now,ll pre){
	dep[now]=dep[pre]+1;
	fa[now]=pre;
	size[now]=1;
	ll to;
	for(ll e=head[now];e;e=w[e].nxt){
		to=w[e].to;
		if(to==pre)continue;
		dfs1(to,now);
		size[now]+=size[to];
		if(size[to]>size[son[now]])son[now]=to;	//更新son 
	} 
}
void dfs2(ll now,ll pre){	//Only rev以序列为key 	;	其余皆以原tree为key 
	if(son[now]){
		seg[son[now]]=++seg[0];
		rev[seg[0]]=son[now];
		top[son[now]]=top[now];
		dfs2(son[now],now);
	}
	ll to;
	for(ll e=head[now];e;e=w[e].nxt){
		to=w[e].to;
		if(!top[to]){	//与dfn[]似,有vis的功能
			seg[to]=++seg[0];
			rev[seg[0]]=to;
			top[to]=to;	//另起门户
			dfs2(to,now); 
		}
	} 
}
void build(ll k,ll l,ll r){
	if(l==r){
		sum[k]=val[rev[l]];	//从序列 => rev => 原tree(val[i]) 
		return;	//递归边界要return 
	}
	ll mid=l+r>>1;
	build(k<<1,l,mid);
	build(k<<1 | 1,mid+1,r); 
	sum[k]=sum[k<<1]+sum[k<<1 | 1]; 
}
void addtip(int k,int l,int r,ll v){
	sum[k]+=(r-l+1)*v;
	tip[k]+=v;
} 
void pushdown(int k,int l,int r,ll mid){
	if(tip[k]==0)return;
	addtip(k<<1,l,mid,tip[k]);
	addtip(k<<1 | 1,mid+1,r,tip[k]);
	tip[k]=0;
} 
void change(ll k,ll l,ll r,ll x,ll v){
	if(x<l || x>r)return;
	if(l==r && l==x){
		sum[k]+=v;
		return;
	}
	ll mid=l+r>>1;
	change(k<<1,l,mid,x,v);
	change(k<<1 | 1,mid+1,r,x,v);
	sum[k]=sum[k<<1]+sum[k<<1 | 1];
	return; 
}
void modify(ll k,ll l,ll r,ll x,ll y,ll v){	//标记永久化 
	if(x>r || y<l)return;
	if(x<=l && y>=r){
		addtip(k,l,r,v);
		return;
	}
	ll mid=l+r>>1;
	//sum[k]+=(ll)(min(r,y)-max(l,x)+1)*v;
	pushdown(k,l,r,mid);
	modify(k<<1,l,mid,x,y,v);
	modify(k<<1 | 1,mid+1,r,x,y,v);
	sum[k]=sum[k<<1]+sum[k<<1 | 1];
}
ll query(ll k,ll l,ll r,ll x,ll y){
	if(x>r || y<l)return 0;
	//if(x<=l && y>=r) return sum[k]+(r-l+1)*tip[k];	//时时刻刻+tip 
	if(x<=l && y>=r) return sum[k];
	//ll res=(ll)(min(r,y)-max(l,x)+1)*tip[k];	//计算本身标签贡献 
	ll res=0;
	ll mid=l+r>>1;
	pushdown(k,l,r,mid);
	res+=query(k<<1,l,mid,x,y);
	res+=query(k<<1 | 1,mid+1,r,x,y);

	return res;	
}
ll ask(ll x,ll y){	//操作序列(线段树前提)	=>	连续性
	ll res=0;
	ll fx=top[x],fy=top[y];
	while(fx!=fy){	//不在一条重链上 
		if(dep[fx]<dep[fy])swap(x,y),swap(fx,fy);
		res+=query(1,1,seg[0],seg[fx],seg[x]);//先查询,后跳跃
		x=fa[fx];fx=top[x]; 
	}
	//在同一条重链上
	if(dep[x]<dep[y])swap(x,y);
	res+=query(1,1,seg[0],seg[y],seg[x]);
	return res; 
	//top fa?都是操作原tree
}
int main() {	//轻重边对称与关联	=>	Only跑1种即可 
	n=readi();m=readi();
	for(ll i=1;i<=n;i++)val[i]=readi();
	for(ll i=1;i<n;i++){
		x=readi();y=readi();
		addlist(x,y);addlist(y,x); 
	}
	//初始化
	dfs1(1,0);
	seg[0]=seg[1]=rev[1]=top[1]=1;	//root手动初始化 => seg[0]为个数 
	dfs2(1,0);
	build(1,1,seg[0]);
	
	//for(ll i=1;i<=n;i++)cout << size[i]<<endl;
	//prllf("%lld\n",ask(1,4));
	for(ll i=1;i<=m;i++){
		type=readi();x=readi();
		if(type==1){
			y=readi();
			change(1,1,seg[0],seg[x],y);	//x => seg => 序列(线段树) 
		}else if(type==2){
			y=readi();
			modify(1,1,seg[0],seg[x],seg[x]+size[x]-1,y);
		}else{
			printf("%lld\n",ask(1,x));
		}
	}
    return 0;
}
2020/10/26 23:05
加载中...