一中模拟赛3.19——时光流转

Description

Solution

离线以后点分
对于每个点,都用这个点的祖先把这个点的子树更新一遍,
考虑到操作时间早的才能更新晚的和题目中说的“路径上边权都大于等于 v a l val ”,
那就用树状数组做一下二维偏序就行了

Code

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rep(i,a,b) for(register int i=(a);i<=(b);++i)
#define dep(i,a,b) for(register int i=(b);i>=(a);--i)
inline char gc(){
	static char buf[100000],*p1=buf,*p2=buf;
	return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int rd(){
	int x=0,fl=1;char ch=gc();
	for(;ch<48||ch>57;ch=gc())if(ch=='-')fl=-1;
	for(;48<=ch&&ch<=57;ch=gc())x=(x<<3)+(x<<1)+(ch^48);
	return x*fl;
}
char pbuf[100000],*pp=pbuf;
inline void pc(char ch){if(pp==pbuf+100000)fwrite(pbuf,1,100000,stdout),pp=pbuf;*pp++=ch;}
inline void wri(ll x){
	static char st[19];
	int tp=0;
	if(x<0)pc(45),x=-x;
	if(!x)pc(48);
	while(x)st[tp++]=x%10|48,x/=10;
	while(tp)pc(st[--tp]);
}
inline void wln(ll x){wri(x),pc(10);}
inline void flush(){fwrite(pbuf,1,pp-pbuf,stdout);}
const int N=100002;
struct node{
	int x,y,v;
	node(){}
	node(int x_,int y_,int v_){x=x_,y=y_,v=v_;}
	bool operator <(node a)const{return x<a.x;}
}A[N],B[N];
struct kk{
	int to,ne,w;
}e[N<<1];
int dep[N],h[N],tot,tot1,tot2,op[N],x,y,z,u,sz[N],n,m,mx[N],rt,st[N];
ll t[N],ans[N];
bool vis[N];
vector<node>md[N];
vector<int>q[N],V;
void add(int x,int y,int z){e[++tot]=(kk){y,h[x],z},h[x]=tot;}
void clear(int x){
	for (;x<=m;x+=x&-x) t[x]=0;
}
void add(int x,int y){
	for (;x<=m;x+=x&-x) t[x]+=y;
}
ll query(int x){
	ll s=0;
	for (;x;x^=x&-x) s+=t[x];
	return s;
}
void getrt(int u,int fa){
	V.push_back(u);
	sz[u]=1,mx[u]=0;
	for (int i=h[u],v;i;i=e[i].ne)
		if (!vis[v=e[i].to] && v!=fa) getrt(v,u),sz[u]+=sz[v],mx[u]=max(mx[u],sz[v]);
}
void init(int u,int fa){
	for (int i=h[u],v;i;i=e[i].ne)
		if ((v=e[i].to)!=fa) dep[v]=dep[u]+1,init(v,u);
}
void dfs1(int u,int w){
	for (int i=0;i<md[u].size();i++)
		if (md[u][i].x<=w) A[++tot1]=md[u][i];
	for (int i=h[u],v;i;i=e[i].ne)
		if (!vis[v=e[i].to] && dep[v]<dep[u]) dfs1(v,min(w,e[i].w));
}
void dfs2(int u,int fa,int w){
	for (int i=0;i<q[u].size();i++) B[++tot2]=node(w,q[u][i],0);
	for (int i=h[u],v;i;i=e[i].ne)
		if (!vis[v=e[i].to] && v!=fa && dep[v]>dep[u]) dfs2(v,u,min(w,e[i].w));
}
void solve(int u){
	tot1=tot2=0;
	dfs1(u,1e9);
	dfs2(u,0,1e9);
	sort(A+1,A+tot1+1);
	sort(B+1,B+tot2+1);
	int j=1;
	rep(i,1,tot2){
		for (;j<=tot1 && A[j].x<=B[i].x;j++) add(A[j].y,A[j].v);
		ans[B[i].y]+=query(B[i].y);
	}
	rep(j,1,tot1) clear(A[j].y);
}
void work(int u){
	V.clear();
	getrt(u,0);
	rt=0;
	if (!V.size()) return;
	for (int i=0;i<V.size();i++){
		int v=V[i];
		mx[v]=max(mx[v],sz[u]-sz[v]);
		if (mx[v]<mx[rt]) rt=v;
	}
	u=rt;
	solve(u),vis[u]=1;
	for (int i=h[u],v;i;i=e[i].ne)
		if (!vis[v=e[i].to]) work(v);
}
int main(){
	n=rd(),m=rd();
	rep(i,1,n) st[i]=rd();
	rep(i,1,n-1) x=rd(),y=rd(),z=rd(),add(x,y,z),add(y,x,z);
	rep(i,1,m){
		op[i]=rd();
		if (op[i]==2){
			x=rd(),y=rd(),u=rd();//x是chg,y是val
			md[u].push_back(node(y,i,x));
		}else{
			x=rd();
			ans[i]=st[x];
			q[x].push_back(i);
		}
	}
	dep[0]=-1,init(1,0);
	mx[0]=1e9;
	work(1);
	rep(i,1,m)
		if (op[i]==1) wln(ans[i]);
	flush();
}

猜你喜欢

转载自blog.csdn.net/xumingyang0/article/details/88687843
今日推荐