wzj的資料結構(負三十)
難度級別:d; 執行時間限制:1000ms; 執行空間限制:262144kb; **長度限制:2000000b
試題描述
給你一棵n個點的無根樹,點和邊上均有權值。請你設計乙個資料結構,回答m次操作。
1 x v:對於樹上的每乙個節點y,如果將x、y在樹上的距離記為d,那麼將y節點的權值加上d*v。
2 x:詢問節點x的權值。
輸入第一行為乙個正整數n。
第二行到第n行每行三個正整數ui,vi,wi。表示一條樹邊從ui到vi,距離為wi。
第n+1行為乙個正整數m。
最後m行每行三個或兩個正整數,格式見題面。
輸出對於每個詢問操作,輸出答案。
輸入示例
101 2 2
1 3 1
1 4 3
1 5 2
4 6 2
4 7 1
6 8 1
7 9 2
7 10 1
91 3 1
1 10 1
2 12 4
2 51 5 1
1 8 1
2 22 9
輸出示例66
1022
24其他說明
對於30%的資料:1<=n,m<=1000
另有50%的資料:1<=n,m<=100000,保證修改操作均在詢問操作之前。
對於100%的資料:1<=n,m<=100000,1<=x<=n,1<=v,wi<=1000
題解:先想用點分治弄離線分數:首先轉化問題,轉換查詢和修改的物件;然後窩萌變形一下查詢所求,dist(x,y)*a[x]=(dep[x]+dep[y])*a[x]=dep[x]*a[x]+dep[y]*a[x];然後窩萌就是要求出dep[x]*a[x]和a[x],這個掃兩遍就好了。。。
1 #include2 #include3 #include4 #include5 #include6 #include7#define pau putchar(' ')
8#define ent putchar('\n')
9using
namespace
std;
10const
int maxn=100000+10,maxm=200000+10,inf=-1u>>1;11
int n,q,a[maxn],cg,f[maxn],siz[maxn],size;bool
vis[maxn];
12struct tedadj[maxm],*fch[maxn],*ms=adj;
13void add(int x,int y,int
w);fch[x]=ms++;
15 *ms=(ted);fch[y]=ms++;
16return;17
}18long
long
ans[maxn],sum,sumd,tsum,tsumd;
19void findcg(int x,int
fa)25 }f[x]=max(mxs,size-siz[x]);if(f[x]return;26
}27void dfs(int x,int fa,int
dis)
34 }return;35
}36void solve(int x=cg)ans[x]+=sum;sum=0;sumd=0;44
while(top--)
47for(ted*e=fch[x];e;e=e->nxt)
51 }return;52
}53 inline int
read()
56while(isdigit(ch))x=10*x+ch-'
0',ch=getchar();
57return x*=sig;58}
59 inline void write(int
x)if(x<0)putchar('
-'),x=-x;
61int len=0,buf[15];while(x)buf[len++]=x%10,x/=10;62
for(int i=len-1;i>=0;i--)putchar(buf[i]+'
0');return;63
}64void
init()
69int
qs[maxn],m;
70void
work()
77 f[cg=0]=size=n;findcg(1,0
);solve();
78for(int i=1;i<=m;i++)printf("
%lld\n
",ans[qs[i]]);
79return;80
}81void
print()
84int main()
85/*
8610
871 2 2
881 3 1
891 4 3
901 5 2
914 6 2
924 7 1
936 8 1
947 9 2
957 10 1966
971 3 1
981 10 1
991 5 1
1001 8 1
1012 2
1022 9
103*/
動態樹做法:%%%小健健,動態樹分治其實就是把重心累成一棵樹,這棵樹保證了樹高logn。窩萌把資訊分三份累加在覆蓋這個操作點的最多logn個重心上,分別是整棵子樹的資訊all,本子樹到重心的父親的距離資訊cha %&!。。。(意會意會。。。),本子樹到重心的距離資訊tre @*%¥%……。。。(意會意會。。。)
有幾個tips!
1.窩萌的一切操作都是在重心樹上進行的!
2.tre,cha,all這些變數名稱好眼熟?(。。。aaa樹!。。。逃。。。
3.相當好寫!壓倒性優勢勝過點分治有木有!
4.為了保持複雜度,詢問兩點距離這裡採用了lca轉rmq,做到了o(nlogn)-o(1)
1 #include2 #include3 #include4 #include5 #include6 #include7#define pau putchar(' ')
8#define ent putchar('\n')
9using
namespace
std;
10const
int maxn=100000+10,maxm=200000+10,inf=-1u>>1;11
struct tedadj[maxm],*fch[maxn],*ms=adj;
12void add(int x,int y,int
w);fch[x]=ms++;
14 *ms=(ted);fch[y]=ms++;
15return;16
}17int siz[maxn],cg,size,f[maxn],dep[maxn],mi[maxm][20
],log[maxm],cnt,pos[maxn],fa[maxn];
18bool vis[maxn];long
long
all[maxn],cha[maxn],tre[maxn];
19void dfs(int x,int
fa)25 }return;26
}27void
initrmq()
33int dist(int x,int
y)37
void findcg(int x,int
fa)43 }f[x]=max(mxs,size-siz[x]);if(f[x]return;44
}45void solve(int x=cg)
51 }return;52
}53void update(int x,int
v)return;59
}60long
long query(int
x)return
ans;66}
67 inline int
read()
73 inline void write(long
long
x)if(x<0)putchar('
-'),x=-x;
75int len=0;long
long buf[20];while(x)buf[len++]=x%10,x/=10;76
for(int i=len-1;i>=0;i--)putchar(buf[i]+'
0');return;77
}78intn,q;
79void
init()
88return;89
}90void
work()
93void
print()
96int main()
97/*987
991 5 4
1001 2 5
1011 3 1
1023 6 2
1033 4 6
1044 7 2
1051 6
106*/
COJ1013 WZJ的資料結構(十三)
這道題有這樣乙個解法 首先把邊依次加到圖中,若當前這條邊與圖中的邊形成了環,那麼把這個環中最早加進來的邊彈出去 並將每條邊把哪條邊彈了出去記錄下來 ntr i j,特別地,要是沒有彈出邊,ntr i 0 這個顯然是可以用lct來弄的對吧。然後對於每個詢問,我們的答案就是對l r中ntr小於l的邊求和...
COJ0985 WZJ的資料結構(負十五)
coj0985 wzj的資料結構 負十五 試題描述 chx有乙個問題想問問大家。給你乙個長度為n的數列a,請你找到兩個位置l,r,使得a l a l 1 a r 中沒有重複的數,輸出r l 1的最大值。以上是附中聯賽加試的一道題。wzj覺得這道題太水了,改了改題目 wzj有乙個問題想問問大家。給你乙...
COJ0989 WZJ的資料結構(負十一)
coj0989 wzj的資料結構 負十一 試題描述 給出以下定義 1.若子串行 l,r 的極差 最大值 最小值 m,則子串行 l,r 為乙個均勻序列。2.均勻序列 l,r 的權值為sum l,r 即序列的元素和。現在給你乙個長度為n的整數序列a,請你求出權值前k大的均勻序列,輸出k行為它們的權值。輸...