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;
}