记录编号 255333 评测结果 AAAAAAAAAA
题目名称 2288.[HZOI 2015]疯狂的魔法树 最终得分 100
用户昵称 Aglove 是否通过 通过
代码语言 C++ 运行时间 1.760 s
提交时间 2016-04-27 16:46:15 内存使用 9.25 MiB
显示代码纯文本
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<vector>
using namespace std;

const int maxn=200010;
int n,m,u,v,blo,a,b,now,val;
int c[maxn],tot=1;
int fa[maxn];
int pos[maxn];
int add[100010],vis[100010];
vector<int>V[50010];
int ans=0;
struct Graph{
	int h[maxn],cnt;
	int next[maxn<<1],to[maxn<<1];
	void add(int x,int y){++cnt;next[cnt]=h[x];h[x]=cnt;to[cnt]=y;}
}G,T;
bool cmp(const int &a,const int &b){return c[a]<c[b];}
void read(int &num){
	num=0;char ch=getchar();
	while(ch<'!')ch=getchar();
	while(ch>='0'&&ch<='9')num=num*10+ch-'0',ch=getchar();
}
void Get_block(int u,int f){
	fa[u]=f;
	if(V[pos[f]].size()==blo){
		tot++;pos[u]=tot;
		T.add(pos[f],tot);
		V[tot].push_back(u);
	}else pos[u]=pos[f],V[pos[f]].push_back(u);
	for(int i=G.h[u];i;i=G.next[i]){
		int v=G.to[i];
		if(v==f)continue;
		Get_block(v,u);
	}return;
}
int Get_up(vector<int>&V,int v){
	int L=0,R=V.size()-1;
	if(c[V[0]]>v)return -1;
	while(L<R){
		int mid=L+((R-L+1)>>1);
		if(c[V[mid]]<=v)L=mid;
		else R=mid-1;
	}return L;
}
int Get_low(vector<int>&V,int v){
	int L=0,R=V.size()-1;
	if(c[V[R]]<v)return -1;
	while(L<R){
		int mid=(L+R)>>1;
		if(c[V[mid]]>=v)R=mid;
		else L=mid+1;
	}return R;
}
int judge(int u){
	if(vis[u]){
		if(vis[u]>=a&&vis[u]<=b)return V[u].size();
		else return 0;
	}
	int L=Get_low(V[u],a-add[u]);
	int R=Get_up(V[u],b-add[u]);
	if(L==-1||R==-1)return 0;
	return (R-L+1);
}
void DFS_Block(int u){
	ans+=judge(u);
	for(int i=T.h[u];i;i=T.next[i]){
		int v=T.to[i];
		DFS_Block(v);
	}return;
}
void DFS_Point(int u){
	if(c[u]+add[pos[u]]>=a&&c[u]+add[pos[u]]<=b)ans++;
	for(int i=G.h[u];i;i=G.next[i]){
		int v=G.to[i];
		if(v==fa[u])continue;
		if(pos[v]==pos[u])DFS_Point(v);
		else DFS_Block(pos[v]);
	}return;
}
void push_down(int u){
	int sz=V[u].size();
	for(int i=0;i<sz;++i)c[V[u][i]]=vis[u];
	vis[u]=0;
}
void Block_add(int u){
	if(vis[u])vis[u]+=val;
	else add[u]+=val;
	for(int i=T.h[u];i;i=T.next[i]){
		int v=T.to[i];
		Block_add(v);
	}return;
}
void Point_add(int u){
	c[u]+=val;
	for(int i=G.h[u];i;i=G.next[i]){
		int v=G.to[i];
		if(v==fa[u])continue;
		if(pos[v]==pos[u])Point_add(v);
		else Block_add(pos[v]);
	}return;
}
void Block_modify(int u){
	add[u]=0;vis[u]=val;
	for(int i=T.h[u];i;i=T.next[i]){
		int v=T.to[i];
		Block_modify(v);
	}return;
}
void Point_modify(int u){
	c[u]=val-add[pos[u]];
	for(int i=G.h[u];i;i=G.next[i]){
		int v=G.to[i];
		if(v==fa[u])continue;
		if(pos[v]==pos[u])Point_modify(v);
		else Block_modify(pos[v]);
	}return;
}
void debug(){
	for(int i=1;i<=tot;++i){
		if(vis[i])push_down(i);
		sort(V[i].begin(),V[i].end(),cmp);
	}
	for(int i=1;i<=n;++i){
		printf("%d ",c[i]+add[pos[i]]);
	}printf("\n");
}

int main(){
	freopen("H_Tree.in","r",stdin);
	freopen("H_Tree.out","w",stdout);
	read(n);read(m);
	for(int i=1;i<=n;++i)read(c[i]);
	for(int i=1;i<n;++i){
		read(u);read(v);
		G.add(u,v);G.add(v,u);
	}blo=250;pos[0]=1;Get_block(1,0);
	for(int i=1;i<=tot;++i)sort(V[i].begin(),V[i].end(),cmp);
	//for(int i=1;i<=n;++i)printf("%d ",pos[i]);
	//printf("\n");
	while(m--){
		char ch=getchar();
		while(ch<'!')ch=getchar();
		if(ch=='Q'){
			read(u);read(a);read(b);
			ans=0;now=pos[u];
			if(vis[now])push_down(now);
			DFS_Point(u);
			printf("%d\n",ans);
		}else if(ch=='M'){
			read(u);read(val);
			now=pos[u];
			if(vis[now])push_down(now);
			c[u]=val-add[now];
			sort(V[now].begin(),V[now].end(),cmp);
		}else if(ch=='C'){
			read(u);read(val);
			now=pos[u];
			if(vis[now])push_down(now);
			Point_add(u);
			sort(V[now].begin(),V[now].end(),cmp);
		}else if(ch=='W'){
			read(u);read(val);
			now=pos[u];
			if(vis[now])push_down(now);
			Point_modify(u);
			sort(V[now].begin(),V[now].end(),cmp);
		}else{
			read(u);read(v);
			++n;fa[n]=u;c[n]=v;
			G.add(u,n);
			if(V[pos[u]].size()==blo){
				++tot;pos[n]=tot;
				T.add(pos[u],tot);
				V[tot].push_back(n);
			}else{
				now=pos[u];
				if(vis[now])push_down(now);
				pos[n]=pos[u];c[n]=v-add[now];
				V[now].push_back(n);
				sort(V[now].begin(),V[now].end(),cmp);
			}
		}
	}return 0;
}