HDU 3966 Aragorn's Story 树链剖分+线段树

                                 Aragorn's Story

                  Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
                             Total Submission(s): 16365    Accepted Submission(s): 4289

题意:

给你一棵树,从  1 到 n 编号,树上的每个点有权值,有3种操作:

           I   x  y  z        从树上 x 号点到 y 号点的路径上的每个点(包括 x , y ) 增加 z 

           D   x  y  z        从树上 x 号点到 y 号点的路径上的每个点(包括 x , y ) 减少z 

           Q   x            询问第 x 号点的权值,需要你回答它

分析:

首先   树链剖分 + 线段树

其次   有区间修改,所以我打了 lazy 防超时

最后   它每次只询问单个点,所以选择用一个数组  ans [ i ] 直接保存 线段树上第 i 号点的权值

PS:

1. 多组数据,清空cnt K  等计数变量  && 数组等

2. 注意细节

3. 如果你RE了:请注意  原树上的 点、权值 和  线段树上的  点、权值

                           不要盲目改代码,最好静态差错(一般是小错误)

贴上AC代码:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>

using namespace std;

const int N = 50005;

inline void wprint (int x){
	if (x>9)	wprint(x/10);
	putchar(x%10+'0');
}

inline void print (int x){
	if (x<0) x=-x,putchar('-');
	wprint(x);
	putchar('\n');
}

inline int wread(){
	char c(getchar());int wans(0),flag(1);
	while (c<'0' || c>'9') {if (c=='-') flag=-1;c=getchar();}
	while (c>='0' && c<='9'){wans=wans*10+c-'0'; c=getchar();}
	return wans*=flag;
}
int n,m,k;
int w[N];
int K,hed[N];
struct node{int v,nxt;}e[100000];
void ad (int u,int v){e[++K].v=v; e[K].nxt=hed[u]; hed[u]=K;}

int f[N], son[N], siz[N], dep[N];

void dfs1(int x,int fa){
	son[x]=-1;
	siz[x]=1;
	f[x]=fa;
	for (int i(hed[x]);i!=-1;i=e[i].nxt){
		int v(e[i].v);
		if (v==fa)	continue;
		dep[v]=dep[x]+1;
		dfs1(v,x);
		siz[x]+=siz[v];
		if (son[x]==-1 || siz[v] > siz[son[x]])
			son[x]=v;

	}
}

int nid[N], rnk[N], top[N], cnt;

void dfs2(int x,int sp){
	nid[x]=++cnt;
	rnk[cnt]=x;
	top[x]=sp;
	if ( son[x] !=-1 )	dfs2(son[x],sp);
	for (int i(hed[x]);i!=-1;i=e[i].nxt){
		int v(e[i].v);
		if (v==f[x] || v==son[x])	continue;
		dfs2(v,v);
	}
}

struct node2{int l,r,lzy;}tre[200005];
int ans[N];

void make_tre(int a,int l,int r){
	tre[a].l=l; tre[a].r=r; tre[a].lzy=0; 
	if (l==r){ans[l]=w[rnk[l]]; return ;}
	int mid(l+r>>1),lson(a<<1),rson(a<<1|1);
	make_tre(lson,l,mid);
	make_tre(rson,mid+1,r);
	return ;
}

void xia_fang (int a){
	int lson((a<<1)), rson(a<<1|1);
	tre[lson].lzy+=tre[a].lzy;
	tre[rson].lzy+=tre[a].lzy;
	tre[a].lzy=0;
}

int get_ans(int a,int pos){
	if (tre[a].l==pos && tre[a].r==pos)	{ans[pos]+=tre[a].lzy;tre[a].lzy=0;return ans[pos];}
	if (tre[a].lzy)	xia_fang(a);
	int mid(tre[a].l + tre[a].r >>1),lson(a<<1),rson(a<<1|1);
	if (pos<=mid)	return get_ans(lson,pos);
	else return get_ans(rson,pos);
}

void add_qu(int a,int l,int r,int k){
	if (tre[a].l>=l && tre[a].r<=r )	{tre[a].lzy+=k;return ;}
	if (tre[a].lzy)	xia_fang(a);
	int mid(tre[a].l+tre[a].r>>1), lson(a<<1), rson(a<<1|1);
	if (r<=mid)	add_qu(lson, l, r, k);
	else if (l>mid)	add_qu(rson, l, r, k);
	else add_qu(lson, l, r, k),add_qu(rson, l, r, k);
}

void add_peo (int x,int y,int z){//节点x ~节点y +z 
	while (top[x] != top[y] ){
		if (dep[top[x]]<dep[top[y]])	swap(x,y);
		add_qu(1,nid[top[x]],nid[x],z);
		x=f[top[x]];
	}
	if (dep[x]<dep[y])	swap(x,y);
	add_qu(1,nid[y],nid[x],z);
	return ;
}


int main (){
	while (~scanf("%d%d%d",&n,&m,&k)){
		cnt=0;K=0;
		memset(hed,-1,sizeof hed);
		for (int i(1);i<=n;++i)
			w[i]=wread();
		for (int i(1);i<=m;++i){
			int u(wread()),v(wread());
			ad(u,v);ad(v,u);
		}
		dep[1]=1;
		dfs1(1,1);
		dfs2(1,1);
		make_tre(1,1,n);
		while (k--){
			char s[4];
			scanf ("%s",s);
			if (s[0]=='I'){
				int x(wread()),y(wread()),z(wread());
				add_peo(x,y,z);
			}
			else if (s[0]=='D'){
				int x(wread()),y(wread()),z(wread());
				add_peo(x,y,-z);
			}
			else{
				int pos(wread());
				print(get_ans(1,nid[pos]));
			}
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/violinlove/article/details/81209991