树链剖分练习题
树链剖分练习题
洛谷补题链接
P3038 USACO11DEC]Grass Planting G
/*
2020/8/17/8:34
树链剖分:含点权转边权处理。
*/
#include<bits/stdc++.h>
using namespace std;
#define rep(i, a, n) for(int i = a; i <= n; ++ i);
#define per(i, a, n) for(int i = n; i >= a; -- i);
typedef long long ll;
const int N = 2e6+ 5;
const ll mod = 1e9 + 7;
const double Pi = acos(- 1.0);
const int INF = 0x3f3f3f3f;
const int G = 3, Gi = 332748118;
ll qpow(ll a, ll b) { ll res = 1; while(b){ if(b & 1) res = (res * a) % mod; a = (a * a) % mod; b >>= 1;} return res; }
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
ll lcm(ll a, ll b) { return a * b / gcd(a, b);}
bool cmp(int a, int b){ return a > b;}
//
int n, m, r;
int head[N], cnt = 0;
struct node{
int to, nxt, c;
}edge[N << 1];
struct Tree{
int l, r, val, lz;
}tree[N * 4];
int val[N], tval[N];
int son[N], siz[N],dfn[N], dep[N], top[N], fa[N], rnk[N];
int res = 0, tot = 0;
void add(int u, int v){
edge[cnt].to = v, edge[cnt].nxt = head[u], head[u] = cnt ++;
edge[cnt].to = u, edge[cnt].nxt = head[v], head[v] = cnt ++;
}
void pushdown(int index){
if(tree[index].lz){
tree[index << 1].val += (tree[index << 1].r - tree[index << 1].l + 1) * tree[index].lz;
tree[index << 1 | 1].val += (tree[index<<1|1].r - tree[index<<1|1].l + 1) * tree[index].lz;
tree[index << 1].lz += tree[index].lz;
tree[index << 1 | 1].lz += tree[index].lz;
tree[index].lz = 0;
}
}
void pushup(int index){
tree[index].val = (tree[index << 1].val + tree[index << 1 | 1].val);
}
void Build(int l, int r, int index){
tree[index].l = l, tree[index].r = r;
tree[index].lz = 0;
if(l == r){
tree[index].val = 0;
return;
}
int mid = (l + r) >> 1;
Build(l, mid, index << 1);
Build(mid + 1, r, index << 1 | 1);
pushup(index);
}
void updata(int l, int r, int index, int val){
if(tree[index].l >= l && tree[index].r <= r){
tree[index].lz += val;
tree[index].val += (tree[index].r - tree[index].l + 1) * val;
return;
}
if(tree[index].lz) pushdown(index);
int mid = (tree[index].l + tree[index].r) >> 1;
if(l <= mid) updata(l, r, index << 1, val);
if(r > mid) updata(l, r, index << 1 | 1, val);
pushup(index);
}
int query(int l, int r, int index){
if(l <= tree[index].l && tree[index].r <= r){
return tree[index].val;
}
if(tree[index].lz) pushdown(index);
int mid = (tree[index].l + tree[index].r) >> 1;
int ans = 0;
if(l <= mid) ans += query(l, r, index << 1);
if(r > mid) ans += query(l, r, index << 1 | 1);
return ans;
}
// --------------------------------
int qRange(int x, int y){ //x 到 y树上最短路径结点权值和
int res = 0;
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]]) swap(x, y);
res += query(dfn[top[x]], dfn[x], 1);
x = fa[top[x]];
}
if(dep[x] > dep[y]) swap(x, y);
res += query(dfn[x] + 1, dfn[y], 1);
return res;
}
void updRange(int x, int y, int c){ //x 到 y最短路径上点值 + z
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]]) swap(x, y);
updata(dfn[top[x]], dfn[x], 1, c);
x = fa[top[x]];
}
if(dep[x] > dep[y]) swap(x, y);
updata(dfn[x] + 1, dfn[y], 1, c);
}
int qSon(int x){ //以x为根结点的子树内所有节点值之和
return query(dfn[x], dfn[x] + siz[x] - 1, 1);
}
void updSon(int x, int val){ //以x为根的子树内所有节点值 + z
updata(dfn[x], dfn[x] + siz[x] - 1, 1, val);
}
void dfs1(int u, int pre){
dep[u] = dep[pre] + 1;
fa[u] = pre;
siz[u] = 1;
int maxx = -1;
for(int i = head[u]; i != -1; i = edge[i].nxt){
int v = edge[i].to;
if(v == pre) continue;
dfs1(v, u);
siz[u] += siz[v];
if(siz[v] > maxx){
maxx = siz[v];
son[u] = v;
}
}
}
void dfs2(int u, int topu){ //topu当前链的最顶端的节点
dfn[u] = ++ tot;
tval[tot] = val[u];
top[u] = topu;
rnk[tot] = u;
if(!son[u]) return;
dfs2(son[u], topu);
for(int i = head[u]; i != -1; i = edge[i].nxt){
int v = edge[i].to;
if(v == son[u] || v == fa[u]) continue;
dfs2(v, v);
}
}
//树链剖分求LCA
int lca(int x, int y){
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]]) swap(x, y);
x = fa[top[x]];
}
if(dep[x] < dep[y]) return x;
else return y;
}
int main()
{
scanf("%d%d",&n,&m);
cnt = 0;
for(int i = 0; i <= n; ++ i) head[i] = -1;
for(int i = 1; i < n; ++ i){
int x, y; scanf("%d%d",&x,&y);
add(x, y);
}
dfs1(1, 1);
dfs2(1, 1);
Build(1, n, 1);
char s[5];
while(m --){
int x, y; scanf("%s%d%d",s,&x,&y);
if(s[0] == 'P'){
updRange(x, y, 1);
}
else{
printf("%d\n",qRange(x, y));
}
}
return 0;
}
P3128 USACO15DEC]Max Flow P
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#include<cmath>
using namespace std;
typedef long long ll;
const int MA=5e4+5;
int n,cnt=0,t,k,ans;
int head[MA],f[MA][30],d[MA],txt[MA],fa[MA];
struct node
{
int to;
int next;
}edge[MA*3];
queue<int>q;
inline void add(int u,int v)
{
edge[++cnt].to=v;
edge[cnt].next=head[u];
head[u]=cnt;
}
void bfs()
{
q.push(1);
d[1]=1;
while(!q.empty()){
int u=q.front();
q.pop();
for(int i=head[u];i;i=edge[i].next){
int v=edge[i].to;
if(d[v])continue;
fa[v]=u;
d[v]=d[u]+1;
f[v][0]=u;
for(int j=1;j<=t;++j)
f[v][j]=f[f[v][j-1]][j-1];
q.push(v);
}
}
}
void dfs(int u,int pre)
{
for(int i=head[u];i;i=edge[i].next){
int v=edge[i].to;
if(v==pre)continue;
dfs(v,u);
txt[u]+=txt[v];
ans=max(ans,txt[u]);
}
}
int LCA(int x,int y)
{
if(d[x]>d[y])swap(x,y);
for(int i=t;i>=0;--i)
if(d[f[y][i]]>=d[x])y=f[y][i];
if(x==y)return x;
for(int i=t;i>=0;--i)
if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
return f[x][0];
}
int main()
{
scanf("%d%d",&n,&k);
t=(int)(log(n)/log(2))+1;
for(int i=1;i<n;++i){
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
bfs();
for(int i=1;i<=k;++i){
int x,y;
scanf("%d%d",&x,&y);
txt[x]+=1;
txt[y]+=1;
txt[LCA(x,y)]-=1;
txt[fa[LCA(x,y)]]-=1;
}
ans=0;
dfs(1,0);
printf("%d\n",ans);
return 0;
}
P4427 BJOI2018]求和
/*
P4427
2020/8/17/11:02
*/
#include<bits/stdc++.h>
using namespace std;
#define rep(i, a, n) for(int i = a; i <= n; ++ i);
#define per(i, a, n) for(int i = n; i >= a; -- i);
typedef long long ll;
const int N = 4e5+ 5;
const ll mod = 998244353;
const double Pi = acos(- 1.0);
const int INF = 0x3f3f3f3f;
const int G = 3, Gi = 332748118;
ll qpow(ll a, ll b) { ll res = 1; while(b){ if(b & 1) res = (res * a) % mod; a = (a * a) % mod; b >>= 1;} return res; }
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
ll lcm(ll a, ll b) { return a * b / gcd(a, b);}
bool cmp(int a, int b){ return a > b;}
//
inline int read(){
register int ans=0;register char c=getchar();register bool neg=0;
while((c<'0')|(c>'9')) neg^=!(c^'-'),c=getchar();
while((c>='0')&(c<='9')) ans=(ans<<3)+(ans<<1)+c-'0',c=getchar();
return neg?-ans:ans;
}
inline void write(int x)
{
if(x<0)
{
putchar('-');
x=-x;
}
if(x>9) write(x/10);
putchar(x%10+'0');
}
int n, m, k;
int head[N], cnt = 0;
struct node{
int to, nxt, c;
}edge[N << 1];
struct Tree{
int l, r; ll val, lz;
}tree[N * 4];
int tval[N];
int son[N], siz[N],dfn[N], dep[N], top[N], fa[N];
ll sol[N][60];
int tot = 0;
void add(int u, int v){
edge[cnt].to = v, edge[cnt].nxt = head[u], head[u] = cnt ++;
edge[cnt].to = u, edge[cnt].nxt = head[v], head[v] = cnt ++;
}
void dfs1(int u, int pre){
dep[u] = dep[pre] + 1;
fa[u] = pre;
siz[u] = 1;
int maxx = -1;
for(int i = 0; i <= 50; ++ i){
sol[u][i] = sol[pre][i] + qpow(dep[u], i);
sol[u][i] %= mod;
}
for(int i = head[u]; i != -1; i = edge[i].nxt){
int v = edge[i].to;
if(v == pre) continue;
dfs1(v, u);
siz[u] += siz[v];
if(siz[v] > maxx){
maxx = siz[v];
son[u] = v;
}
}
}
void dfs2(int u, int topu){ //topu当前链的最顶端的节点
dfn[u] = ++ tot;
tval[tot] = dep[u];
top[u] = topu;
if(!son[u]) return;
dfs2(son[u], topu);
for(int i = head[u]; i != -1; i = edge[i].nxt){
int v = edge[i].to;
if(v == son[u] || v == fa[u]) continue;
dfs2(v, v);
}
}
//树链剖分求LCA
int LCA(int x, int y){
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]]) swap(x, y);
x = fa[top[x]];
}
if(dep[x] < dep[y]) return x;
else return y;
}
void tree_cut(){
dep[0] = -1;
dfs1(1, 0);
dfs2(1, 1);
}
int main()
{
n = read();
cnt = 0;
for(int i = 0; i <= n; ++ i) head[i] = -1;
for(int i = 1; i < n; ++ i){
int x, y; x = read(); y = read();
add(x, y);
}
tree_cut();
m = read();
while(m --){
int x, y; x = read(); y = read(); k = read();
int lca = LCA(x, y);
ll res = (sol[x][k] + sol[y][k]) % mod;
res = ((res - sol[fa[lca]][k] + mod) % mod - sol[lca][k] + mod) % mod;
write(res);
puts("");
}
return 0;
}
P6098 USACO19FEB]Cow Land G
/*
2020/8/17/12:04
*/
#include<bits/stdc++.h>
using namespace std;
#define rep(i, a, n) for(int i = a; i <= n; ++ i);
#define per(i, a, n) for(int i = n; i >= a; -- i);
typedef long long ll;
const int N = 2e6+ 5;
const ll mod = 1e9 + 7;
const double Pi = acos(- 1.0);
const int INF = 0x3f3f3f3f;
const int G = 3, Gi = 332748118;
ll qpow(ll a, ll b) { ll res = 1; while(b){ if(b & 1) res = (res * a) % mod; a = (a * a) % mod; b >>= 1;} return res; }
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
ll lcm(ll a, ll b) { return a * b / gcd(a, b);}
bool cmp(int a, int b){ return a > b;}
//
// int tpp[N];
int n, m, r;
int head[N], cnt = 0;
struct node{
int to, nxt, c;
}edge[N << 1];
struct Tree{
int l, r, val, lz;
}tree[N * 4];
int val[N], tval[N];
int son[N], siz[N],dfn[N], dep[N], top[N], fa[N], rnk[N];
int res = 0, tot = 0;
void add(int u, int v){
edge[cnt].to = v, edge[cnt].nxt = head[u], head[u] = cnt ++;
edge[cnt].to = u, edge[cnt].nxt = head[v], head[v] = cnt ++;
}
void pushup(int index){
tree[index].val = (tree[index << 1].val ^ tree[index << 1 | 1].val);
}
void Build(int l, int r, int index){
tree[index].l = l, tree[index].r = r;
tree[index].lz = 0;
if(l == r){
// tpp[l] = index;
tree[index].val = tval[l];
return;
}
int mid = (l + r) >> 1;
Build(l, mid, index << 1);
Build(mid + 1, r, index << 1 | 1);
pushup(index);
}
void updata(int l, int r, int index, int val){
if(tree[index].l == tree[index].r){
tree[index].val = val;
return;
}
int mid = (tree[index].l + tree[index].r) >> 1;
if(l <= mid) updata(l, r, index << 1, val);
if(r > mid) updata(l, r, index << 1 | 1, val);
pushup(index);
}
int query(int l, int r, int index){
if(l <= tree[index].l && tree[index].r <= r){
return tree[index].val;
}
int mid = (tree[index].l + tree[index].r) >> 1;
int ans = 0;
if(l <= mid) ans ^= query(l, r, index << 1);
if(r > mid) ans ^= query(l, r, index << 1 | 1);
return ans;
}
// --------------------------------
int qRange(int x, int y){ //x 到 y树上最短路径结点权值和
int res = 0;
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]]) swap(x, y);
res ^= query(dfn[top[x]], dfn[x], 1);
x = fa[top[x]];
}
if(dep[x] > dep[y]) swap(x, y);
res ^= query(dfn[x], dfn[y], 1);
return res;
}
void updRange(int x, int y, int c){ //x 到 y最短路径上点值 + z
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]]) swap(x, y);
updata(dfn[top[x]], dfn[x], 1, c);
x = fa[top[x]];
}
if(dep[x] > dep[y]) swap(x, y);
updata(dfn[x], dfn[y], 1, c);
}
void dfs1(int u, int pre){
dep[u] = dep[pre] + 1;
fa[u] = pre;
siz[u] = 1;
int maxx = -1;
for(int i = head[u]; i != -1; i = edge[i].nxt){
int v = edge[i].to;
if(v == pre) continue;
dfs1(v, u);
siz[u] += siz[v];
if(siz[v] > maxx){
maxx = siz[v];
son[u] = v;
}
}
}
void dfs2(int u, int topu){ //topu当前链的最顶端的节点
dfn[u] = ++ tot;
tval[tot] = val[u];
top[u] = topu;
if(!son[u]) return;
dfs2(son[u], topu);
for(int i = head[u]; i != -1; i = edge[i].nxt){
int v = edge[i].to;
if(v == son[u] || v == fa[u]) continue;
dfs2(v, v);
}
}
int main()
{
scanf("%d%d",&n,&m);
cnt = 0;
for(int i = 0; i <= n ; ++ i) head[i] = -1;
for(int i = 1; i <= n; ++ i) scanf("%d",&val[i]);
for(int i = 1; i < n; ++ i){
int x, y; scanf("%d%d",&x,&y);
add(x, y);
}
dfs1(1, 1);
dfs2(1, 1);
Build(1, n, 1);
while(m --){
int op, x, y;
scanf("%d%d%d",&op,&x,&y);
if(op == 1){
updRange(x, x, y);
}
else{
printf("%d\n",qRange(x, y));
}
// for(int i = 1; i <= n; ++ i){
// cout<<tree[tpp[i]].val<<" ";
// }
// cout<<endl;
}
return 0;
}
P4092 HEOI2016/TJOI2016]树
/*
2020/8/17/13:04
*/
#include<bits/stdc++.h>
using namespace std;
#define rep(i, a, n) for(int i = a; i <= n; ++ i);
#define per(i, a, n) for(int i = n; i >= a; -- i);
typedef long long ll;
const int N = 2e6+ 5;
const ll mod = 1e9 + 7;
const double Pi = acos(- 1.0);
const int INF = 0x3f3f3f3f;
const int G = 3, Gi = 332748118;
ll qpow(ll a, ll b) { ll res = 1; while(b){ if(b & 1) res = (res * a) % mod; a = (a * a) % mod; b >>= 1;} return res; }
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
ll lcm(ll a, ll b) { return a * b / gcd(a, b);}
bool cmp(int a, int b){ return a > b;}
//
int n, m, r;
int head[N], cnt = 0;
struct node{
int to, nxt, c;
}edge[N << 1];
struct Tree{
int l, r, val, lz;
}tree[N * 4];
int val[N], tval[N];
int son[N], siz[N],dfn[N], dep[N], top[N], fa[N], rnk[N];
int res = 0, tot = 0;
void add(int u, int v){
edge[cnt].to = v, edge[cnt].nxt = head[u], head[u] = cnt ++;
edge[cnt].to = u, edge[cnt].nxt = head[v], head[v] = cnt ++;
}
void pushup(int index){
tree[index].val = max(tree[index << 1].val , tree[index << 1 | 1].val);
}
void Build(int l, int r, int index){
tree[index].l = l, tree[index].r = r;
tree[index].lz = 0;
if(l == r){
tree[index].val = 0;
return;
}
int mid = (l + r) >> 1;
Build(l, mid, index << 1);
Build(mid + 1, r, index << 1 | 1);
pushup(index);
}
void updata(int l, int r, int index, int val){
if(tree[index].l >= l && tree[index].r <= r){
tree[index].val = val;
return;
}
int mid = (tree[index].l + tree[index].r) >> 1;
if(l <= mid) updata(l, r, index << 1, val);
if(r > mid) updata(l, r, index << 1 | 1, val);
pushup(index);
}
int query(int l, int r, int index){
if(l <= tree[index].l && tree[index].r <= r){
return tree[index].val;
}
int mid = (tree[index].l + tree[index].r) >> 1;
int ans = 0;
if(r > mid) ans = query(l, r, index << 1 | 1);
if(l <= mid) ans = max(ans, query(l, r, index << 1));
return ans;
}
// --------------------------------
int qRange(int x, int y){ //x 到 y树上最短路径结点权值和
int res = 0;
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]]) swap(x, y);
int tt = query(dfn[top[x]], dfn[x], 1);
if(tt != 0) return tt;
x = fa[top[x]];
}
if(dep[x] > dep[y]) swap(x, y);
return query(dfn[x], dfn[y], 1);
}
void dfs1(int u, int pre){
dep[u] = dep[pre] + 1;
fa[u] = pre;
siz[u] = 1;
int maxx = -1;
for(int i = head[u]; i != -1; i = edge[i].nxt){
int v = edge[i].to;
if(v == pre) continue;
dfs1(v, u);
siz[u] += siz[v];
if(siz[v] > maxx){
maxx = siz[v];
son[u] = v;
}
}
}
void dfs2(int u, int topu){ //topu当前链的最顶端的节点
dfn[u] = ++ tot;
top[u] = topu;
rnk[tot] = u;
if(!son[u]) return;
dfs2(son[u], topu);
for(int i = head[u]; i != -1; i = edge[i].nxt){
int v = edge[i].to;
if(v == son[u] || v == fa[u]) continue;
dfs2(v, v);
}
}
int main()
{
scanf("%d%d",&n,&m);
cnt = 0;
for(int i = 0; i <= n; ++ i) head[i] = -1;
for(int i = 1; i < n; ++ i){
int x, y; scanf("%d%d",&x,&y);
add(x, y);
}
dfs1(1, 0);
dfs2(1, 1);
Build(1, n, 1);
updata(dfn[1], dfn[1], 1, 1);
char op[5];
while(m --){
int x; scanf("%s%d",op,&x);
if(op[0] == 'C'){
updata(dfn[x], dfn[x], 1, dfn[x]);
}
else{
printf("%d\n",rnk[qRange(1, x)]);
}
}
}
P4315 月下“毛景树”
/*
2020/8/17/19:59
树链剖分:含点权转边权处理。
区间加
区间覆盖
*/
#include<bits/stdc++.h>
using namespace std;
#define rep(i, a, n) for(int i = a; i <= n; ++ i);
#define per(i, a, n) for(int i = n; i >= a; -- i);
typedef long long ll;
const int N = 2e6+ 5;
const ll mod = 1e9 + 7;
const double Pi = acos(- 1.0);
const int INF = 0x3f3f3f3f;
const int G = 3, Gi = 332748118;
ll qpow(ll a, ll b) { ll res = 1; while(b){ if(b & 1) res = (res * a) % mod; a = (a * a) % mod; b >>= 1;} return res; }
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
ll lcm(ll a, ll b) { return a * b / gcd(a, b);}
bool cmp(int a, int b){ return a > b;}
//
int tpp[N];
int n, m;
int ax[N], ay[N];
int head[N], cnt = 0, tot = 0;
int siz[N], dep[N], fa[N], son[N];
int dfn[N], tval[N], val[N], top[N], rnk[N];
struct node{
int to, nxt, c;
}edge[N << 1];
void add(int u, int v, int w){
edge[cnt].to = v, edge[cnt].c = w, edge[cnt].nxt = head[u], head[u] = cnt ++;
edge[cnt].to = u, edge[cnt].c = w, edge[cnt].nxt = head[v], head[v] = cnt ++;
}
struct Tree{
int l, r, val;
int lz1, lz2;
}tree[N * 4];
void pushdown(int index){
if(tree[index].lz1 >= 0){
tree[index << 1].val = tree[index << 1 | 1].val = tree[index].lz1;
tree[index << 1].lz1 = tree[index << 1 | 1].lz1 = tree[index].lz1;
tree[index << 1].lz2 = tree[index << 1 | 1].lz2 = 0;
tree[index].lz1 = -1;
}
if(tree[index].lz2){
tree[index << 1].val += tree[index].lz2; tree[index << 1 | 1].val += tree[index].lz2;
tree[index << 1].lz2 += tree[index].lz2; tree[index << 1 | 1].lz2 += tree[index].lz2;
tree[index].lz2 = 0;
}
}
void pushup(int index){
tree[index].val = max(tree[index << 1].val, tree[index << 1 | 1].val);
}
void Build(int l, int r, int index){
tree[index].l = l; tree[index].r = r;
tree[index].lz1 = -1; tree[index].lz2 = tree[index].val = 0;
if(l == r){
// tpp[l] = index;
tree[index].val = tval[l];
return;
}
int mid = (tree[index].l + tree[index].r) >> 1;
Build(l, mid, index << 1);
Build(mid + 1, r, index << 1 | 1);
pushup(index);
}
void updata1(int l, int r, int index, int val){
if(tree[index].l >= l && tree[index].r <= r){
tree[index].lz1 = val;
tree[index].lz2 = 0;
tree[index].val = val;
return;
}
pushdown(index);
int mid = (tree[index].l + tree[index].r) >> 1;
if(l <= mid) updata1(l, r, index << 1, val);
if(r > mid) updata1(l, r, index << 1 | 1, val);
pushup(index);
}
void updata2(int l, int r, int index, int val){
if(tree[index].l >= l && tree[index].r <= r){
tree[index].lz2 += val;
tree[index].val += val;
return;
}
pushdown(index);
int mid = (tree[index].l + tree[index].r) >> 1;
if(l <= mid) updata2(l, r, index << 1, val);
if(r > mid) updata2(l, r, index << 1 | 1, val);
pushup(index);
}
int query(int l, int r, int index){
if(l <= tree[index].l && tree[index].r <= r){
return tree[index].val;
}
pushdown(index);
int mid = (tree[index].l + tree[index].r) >> 1;
int res = 0;
if(l <= mid) res = max(res, query(l, r, index << 1));
if(r > mid) res = max(res, query(l, r, index << 1 | 1));
return res;
}
//--------------------------
void Change(int x, int val){
updata1(dfn[x], dfn[x], 1, val);
}
void Cover(int x, int y, int val){
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]]) swap(x, y);
updata1(dfn[top[x]], dfn[x], 1, val);
x = fa[top[x]];
}
if(dep[x] > dep[y]) swap(x, y);
updata1(dfn[x] + 1, dfn[y], 1, val);
}
void Add(int x, int y, int val){
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]]) swap(x, y);
updata2(dfn[top[x]], dfn[x], 1, val);
x = fa[top[x]];
}
if(dep[x] > dep[y]) swap(x, y);
updata2(dfn[x] + 1, dfn[y], 1, val);
}
int Max(int x, int y){
int ans = 0;
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]]) swap(x, y);
ans = max(ans, query(dfn[top[x]], dfn[x], 1));
x = fa[top[x]];
}
if(dep[x] > dep[y]) swap(x, y);
ans = max(ans, query(dfn[x] + 1, dfn[y], 1));
return ans;
}
void dfs1(int u, int pre){
dep[u] = dep[pre] + 1;
siz[u] = 1;
fa[u] = pre;
int maxx = -1;
for(int i = head[u]; i != -1; i = edge[i].nxt){
int v = edge[i].to, w = edge[i].c;
if(v == pre) continue;
val[v] = w;
dfs1(v, u);
siz[u] += siz[v];
if(siz[v] > maxx){
maxx = siz[v];
son[u] = v;
}
}
}
void dfs2(int u, int topu){
dfn[u] = ++ tot;
tval[tot] = val[u];
top[u] = topu;
rnk[tot] = u;
if(!son[u]) return;
dfs2(son[u], topu);
for(int i = head[u]; i != -1; i = edge[i].nxt){
int v = edge[i].to, w = edge[i].c;
if(v == son[u] || v == fa[u]) continue;
dfs2(v, v);
}
}
// void print(){
// for(int i = 1; i <= n; ++ i){
// int tt = tpp[dfn[i]];
// cout<<tree[tt].val<<" ";
// }
// cout<<endl;
// }
int main()
{
scanf("%d",&n);
cnt = 0;
for(int i = 0; i <= n; ++ i) head[i] = -1;
for(int i = 1; i < n; ++ i){
int z; scanf("%d%d%d",&ax[i], &ay[i], &z);
add(ax[i], ay[i], z);
}
dfs1(1, 0);
dfs2(1, 1);
Build(1, n, 1);
// print();
char op[10];
while(1){
scanf("%s",op);
if(op[0] == 'S') break;
else if(op[1] == 'h'){ //change
int x, y; scanf("%d%d",&x,&y);
if(dep[ax[x]] < dep[ay[x]]) Change(ay[x], y);
else Change(ax[x], y);
}
else if(op[1] == 'o'){ //Cover
int x, y, z; scanf("%d%d%d",&x,&y,&z);
Cover(x, y, z);
}
else if(op[1] == 'd'){ //Add
int x, y, z; scanf("%d%d%d",&x,&y,&z);
Add(x, y, z);
}
else{
int x, y; scanf("%d%d",&x,&y);
printf("%d\n",Max(x, y));
}
// print();
}
return 0;
}
//
// 8
// 1 2 1
// 2 3 2
// 3 4 1
// 3 7 3
// 4 5 4
// 4 8 2
// 5 6 2
// Max 1 2
// Max 2 7
// Cover 1 7 6
// Max 1 7
// Max 2 7
// Add 2 7 2
// Max 1 7
// Max 2 7
// Cover 1 6 1
P2590 ZJOI2008]树的统计
/*
2020/8/17/19:59
树链剖分:区间最值 + 区间和
线段树维护两个值
*/
#include<bits/stdc++.h>
using namespace std;
#define rep(i, a, n) for(int i = a; i <= n; ++ i);
#define per(i, a, n) for(int i = n; i >= a; -- i);
typedef long long ll;
const int N = 2e6+ 5;
const ll mod = 1e9 + 7;
const double Pi = acos(- 1.0);
const int INF = 0x3f3f3f3f;
const int G = 3, Gi = 332748118;
ll qpow(ll a, ll b) { ll res = 1; while(b){ if(b & 1) res = (res * a) % mod; a = (a * a) % mod; b >>= 1;} return res; }
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
ll lcm(ll a, ll b) { return a * b / gcd(a, b);}
bool cmp(int a, int b){ return a > b;}
//
int tpp[N];
int n, m;
int ax[N], ay[N];
int head[N], cnt = 0, tot = 0;
int siz[N], dep[N], fa[N], son[N];
int dfn[N], tval[N], val[N], top[N], rnk[N];
struct node{
int to, nxt, c;
}edge[N << 1];
void add(int u, int v){
edge[cnt].to = v, edge[cnt].nxt = head[u], head[u] = cnt ++;
edge[cnt].to = u, edge[cnt].nxt = head[v], head[v] = cnt ++;
}
struct Tree{
int l, r, maxx, sum;
}tree[N * 4];
void pushup(int index){
tree[index].maxx = max(tree[index << 1].maxx, tree[index << 1 | 1].maxx);
tree[index].sum = tree[index << 1].sum + tree[index << 1 | 1].sum;
}
void Build(int l, int r, int index){
tree[index].l = l; tree[index].r = r;
tree[index].maxx = -INF; tree[index].maxx = 0;
if(l == r){
// tpp[l] = index;
tree[index].maxx = tval[l];
tree[index].sum = tval[l];
return;
}
int mid = (tree[index].l + tree[index].r) >> 1;
Build(l, mid, index << 1);
Build(mid + 1, r, index << 1 | 1);
pushup(index);
}
void updata(int l, int r, int index, int val){
if(tree[index].l == tree[index].r){
tree[index].maxx = tree[index].sum = val;
return;
}
int mid = (tree[index].l + tree[index].r) >> 1;
if(l <= mid) updata(l, r, index << 1, val);
if(r > mid) updata(l, r, index << 1 | 1, val);
pushup(index);
}
int queryMax(int l, int r, int index){
if(l <= tree[index].l && tree[index].r <= r){
return tree[index].maxx;
}
int mid = (tree[index].l + tree[index].r) >> 1;
int res = -INF;
if(l <= mid) res = max(res, queryMax(l, r, index << 1));
if(r > mid) res = max(res, queryMax(l, r, index << 1 | 1));
return res;
}
int querySum(int l, int r, int index){
if(l <= tree[index].l && tree[index].r <= r){
return tree[index].sum;
}
int mid = (tree[index].l + tree[index].r) >> 1;
int res = 0;
if(l <= mid) res += querySum(l, r, index << 1);
if(r > mid) res += querySum(l, r, index << 1 | 1);
return res;
}
//-------------------------------
void Change(int x, int val){
updata(dfn[x], dfn[x], 1, val);
}
int Sum(int x, int y){
int ans = 0;
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]]) swap(x, y);
ans += querySum(dfn[top[x]], dfn[x], 1);
x = fa[top[x]];
}
if(dep[x] > dep[y]) swap(x ,y);
ans += querySum(dfn[x], dfn[y], 1);
return ans;
}
int Max(int x, int y){
int ans = -INF;
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]]) swap(x, y);
ans = max(ans, queryMax(dfn[top[x]], dfn[x], 1));
x = fa[top[x]];
}
if(dep[x] > dep[y]) swap(x, y);
ans = max(ans, queryMax(dfn[x], dfn[y], 1));
return ans;
}
void dfs1(int u, int pre){
dep[u] = dep[pre] + 1;
siz[u] = 1;
fa[u] = pre;
int maxx = -1;
for(int i = head[u]; i != -1; i = edge[i].nxt){
int v = edge[i].to, w = edge[i].c;
if(v == pre) continue;
dfs1(v, u);
siz[u] += siz[v];
if(siz[v] > maxx){
maxx = siz[v];
son[u] = v;
}
}
}
void dfs2(int u, int topu){
dfn[u] = ++ tot;
tval[tot] = val[u];
top[u] = topu;
rnk[tot] = u;
if(!son[u]) return;
dfs2(son[u], topu);
for(int i = head[u]; i != -1; i = edge[i].nxt){
int v = edge[i].to, w = edge[i].c;
if(v == son[u] || v == fa[u]) continue;
dfs2(v, v);
}
}
// void print(){
// for(int i = 1; i <= n; ++ i){
// int tt = tpp[dfn[i]];
// cout<<tree[tt].maxx<<" ";
// }
// cout<<endl;
// }
int main()
{
scanf("%d",&n);
cnt = 0;
for(int i = 0; i <= n; ++ i) head[i] = -1;
for(int i = 1; i < n; ++ i){
int x, y; scanf("%d%d",&x,&y);
add(x, y);
}
for(int i = 1; i <= n; ++ i) scanf("%d",&val[i]);
dfs1(1, 0);
dfs2(1, 1);
Build(1, n, 1);
// print();
scanf("%d",&m);
char op[10];
while(m --){
scanf("%s",op);
if(op[0] == 'C'){
int x, y; scanf("%d%d",&x,&y);
Change(x, y);
}
else if(op[1] == 'M'){
int x, y; scanf("%d%d",&x,&y);
printf("%d\n",Max(x, y));
}
else if(op[1] == 'S'){
int x, y; scanf("%d%d",&x,&y);
printf("%d\n",Sum(x, y));
}
// print();
}
return 0;
}
P3833 SHOI2012]魔法树
/*
2020/8/17/21:35
*/
#include<bits/stdc++.h>
using namespace std;
#define rep(i, a, n) for(int i = a; i <= n; ++ i);
#define per(i, a, n) for(int i = n; i >= a; -- i);
typedef long long ll;
const int N = 2e6+ 5;
const ll mod = 1e9 + 7;
const double Pi = acos(- 1.0);
const int INF = 0x3f3f3f3f;
const int G = 3, Gi = 332748118;
ll qpow(ll a, ll b) { ll res = 1; while(b){ if(b & 1) res = (res * a) % mod; a = (a * a) % mod; b >>= 1;} return res; }
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
ll lcm(ll a, ll b) { return a * b / gcd(a, b);}
bool cmp(int a, int b){ return a > b;}
//
int tpp[N];
int n, m;
int ax[N], ay[N];
int head[N], cnt = 0, tot = 0;
int siz[N], dep[N], fa[N], son[N];
int dfn[N], tval[N], val[N], top[N], rnk[N];
struct node{
int to, nxt;
}edge[N << 1];
void add(int u, int v){
edge[cnt].to = v, edge[cnt].nxt = head[u], head[u] = cnt ++;
edge[cnt].to = u, edge[cnt].nxt = head[v], head[v] = cnt ++;
}
struct Tree{
int l, r; ll val, lz;
}tree[N * 4];
void pushdown(int index){
if(tree[index].lz){
tree[index << 1].val += (tree[index << 1].r - tree[index << 1].l + 1) * tree[index].lz;
tree[index << 1 | 1].val += (tree[index << 1 | 1].r - tree[index << 1 | 1].l + 1) * tree[index].lz;
tree[index << 1].lz += tree[index].lz;
tree[index << 1 | 1].lz += tree[index].lz;
tree[index].lz = 0;
}
}
void pushup(int index){
tree[index].val = tree[index << 1].val + tree[index << 1 | 1].val;
}
void Build(int l, int r, int index){
tree[index].l = l; tree[index].r = r;
tree[index].val = 0;
if(l == r){
// tpp[l] = index;
return;
}
int mid = (tree[index].l + tree[index].r) >> 1;
Build(l, mid, index << 1);
Build(mid + 1, r, index << 1 | 1);
pushup(index);
}
void updata(int l, int r, int index, ll val){
if(tree[index].l >= l && tree[index].r <= r){
tree[index].lz += val;
tree[index].val += (tree[index].r - tree[index].l + 1) * val;
return;
}
pushdown(index);
int mid = (tree[index].l + tree[index].r) >> 1;
if(l <= mid) updata(l, r, index << 1, val);
if(r > mid) updata(l, r, index << 1 | 1, val);
pushup(index);
}
ll query(int l, int r, int index){
if(tree[index].l >= l && tree[index].r <= r){
return tree[index].val;
}
pushdown(index);
ll ans = 0;
int mid = (tree[index].l + tree[index].r) >> 1;
if(l <= mid) ans += query(l, r, index << 1);
if(r > mid) ans += query(l, r, index << 1 | 1);
return ans;
}
//-------------------------------
void Asol(int x, int y, int val){
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]]) swap(x, y);
updata(dfn[top[x]], dfn[x], 1, val);
x = fa[top[x]];
}
if(dep[x] > dep[y]) swap(x, y);
updata(dfn[x], dfn[y], 1, val);
}
ll Qsol(int x){
return query(dfn[x], dfn[x] + siz[x] - 1, 1);
}
void dfs1(int u, int pre){
dep[u] = dep[pre] + 1;
siz[u] = 1;
fa[u] = pre;
int maxx = -1;
for(int i = head[u]; i != -1; i = edge[i].nxt){
int v = edge[i].to;
if(v == pre) continue;
dfs1(v, u);
siz[u] += siz[v];
if(siz[v] > maxx){
maxx = siz[v];
son[u] = v;
}
}
}
void dfs2(int u, int topu){
dfn[u] = ++ tot;
top[u] = topu;
rnk[tot] = u;
if(!son[u]) return;
dfs2(son[u], topu);
for(int i = head[u]; i != -1; i = edge[i].nxt){
int v = edge[i].to;
if(v == son[u] || v == fa[u]) continue;
dfs2(v, v);
}
}
// void print(){
// for(int i = 1; i <= n; ++ i){
// int tt = tpp[dfn[i]];
// cout<<tree[tt].maxx<<" ";
// }
// cout<<endl;
// }
int main()
{
scanf("%d",&n);
cnt = 0;
for(int i = 0; i <= n; ++ i) head[i] = -1;
for(int i = 1; i < n; ++ i){
int x, y; scanf("%d%d",&x,&y);
add(x + 1, y + 1);
}
dfs1(1, 0);
dfs2(1, 1);
Build(1 , n, 1);
scanf("%d",&m);
char op[10];
while(m --){
scanf("%s",op);
if(op[0] == 'A'){
int x, y; ll z; scanf("%d%d%lld",&x,&y,&z);
x ++; y ++;
Asol(x, y, z);
}
else if(op[0] == 'Q'){
int x; scanf("%d",&x);
x ++;
printf("%lld\n",Qsol(x));
}
}
return 0;
}
P2146 NOI2015]软件包管理器
#include<bits/stdc++.h>
using namespace std;
#define rep(i, a, n) for(int i = a; i <= n; ++ i);
#define per(i, a, n) for(int i = n; i >= a; -- i);
typedef long long ll;
const int N = 2e6+ 5;
const ll mod = 1e9 + 7;
const double Pi = acos(- 1.0);
const int INF = 0x3f3f3f3f;
const int G = 3, Gi = 332748118;
ll qpow(ll a, ll b) { ll res = 1; while(b){ if(b & 1) res = (res * a) % mod; a = (a * a) % mod; b >>= 1;} return res; }
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
ll lcm(ll a, ll b) { return a * b / gcd(a, b);}
bool cmp(int a, int b){ return a > b;}
//
// int tpp[N];
int n, m, r;
int head[N], cnt = 0;
struct node{
int to, nxt, c;
}edge[N << 1];
struct Tree{
int l, r, val, lz;
}tree[N * 4];
int val[N], tval[N];
int son[N], siz[N],dfn[N], dep[N], top[N], fa[N], rnk[N];
int res = 0, tot = 0;
void add(int u, int v){
edge[cnt].to = v, edge[cnt].nxt = head[u], head[u] = cnt ++;
edge[cnt].to = u, edge[cnt].nxt = head[v], head[v] = cnt ++;
}
void pushdown(int index){
tree[index << 1].val = (tree[index << 1].r - tree[index << 1].l + 1) * tree[index].lz;
tree[index << 1 | 1].val = (tree[index<<1|1].r - tree[index<<1|1].l + 1) * tree[index].lz;
tree[index << 1].lz = tree[index].lz;
tree[index << 1 | 1].lz = tree[index].lz;
tree[index].lz = -1;
}
void pushup(int index){
tree[index].val = (tree[index << 1].val + tree[index << 1 | 1].val);
}
void Build(int l, int r, int index){
tree[index].l = l, tree[index].r = r;
tree[index].lz = -1;
if(l == r){
// tpp[l] = index;
tree[index].val = 0;
return;
}
int mid = (l + r) >> 1;
Build(l, mid, index << 1);
Build(mid + 1, r, index << 1 | 1);
pushup(index);
}
void updata(int l, int r, int index, int val){
if(tree[index].l >= l && tree[index].r <= r){
tree[index].lz = val;
tree[index].val = (tree[index].r - tree[index].l + 1) * val;
return;
}
if(tree[index].lz != -1) pushdown(index);
int mid = (tree[index].l + tree[index].r) >> 1;
if(l <= mid) updata(l, r, index << 1, val);
if(r > mid) updata(l, r, index << 1 | 1, val);
pushup(index);
}
int query(int l, int r, int index){
if(l <= tree[index].l && tree[index].r <= r){
return tree[index].val;
}
if(tree[index].lz != -1) pushdown(index);
int mid = (tree[index].l + tree[index].r) >> 1;
int ans = 0;
if(l <= mid) ans += query(l, r, index << 1);
if(r > mid) ans += query(l, r, index << 1 | 1);
return ans;
}
// --------------------------------
int qRange(int x, int y){ //x 到 y树上最短路径结点权值和
int res = 0;
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]]) swap(x, y);
res += query(dfn[top[x]], dfn[x], 1);
x = fa[top[x]];
}
if(dep[x] > dep[y]) swap(x, y);
res += query(dfn[x], dfn[y], 1);
return res % mod;
}
void updRange(int x, int y, int c){ //x 到 y最短路径上点值 + z
c %= mod;
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]]) swap(x, y);
updata(dfn[top[x]], dfn[x], 1, c);
x = fa[top[x]];
}
if(dep[x] > dep[y]) swap(x, y);
updata(dfn[x], dfn[y], 1, c);
}
int qSon(int x){ //以x为根结点的子树内所有节点值之和
return query(dfn[x], dfn[x] + siz[x] - 1, 1);
}
void updSon(int x, int val){ //以x为根的子树内所有节点值 + z
updata(dfn[x], dfn[x] + siz[x] - 1, 1, val);
}
void dfs1(int u, int pre){
dep[u] = dep[pre] + 1;
fa[u] = pre;
siz[u] = 1;
int maxx = -1;
for(int i = head[u]; i != -1; i = edge[i].nxt){
int v = edge[i].to;
if(v == pre) continue;
dfs1(v, u);
siz[u] += siz[v];
if(siz[v] > maxx){
maxx = siz[v];
son[u] = v;
}
}
}
void dfs2(int u, int topu){ //topu当前链的最顶端的节点
dfn[u] = ++ tot;
tval[tot] = val[u];
top[u] = topu;
if(!son[u]) return;
dfs2(son[u], topu);
for(int i = head[u]; i != -1; i = edge[i].nxt){
int v = edge[i].to;
if(v == son[u] || v == fa[u]) continue;
dfs2(v, v);
}
}
int main()
{
scanf("%d",&n);
cnt = 0;
for(int i = 0; i <= n ; ++ i) head[i] = -1;
for(int i = 2; i <= n; ++ i){
int x; scanf("%d",&x);
add(x + 1, i);
}
dfs1(1, 1);
dfs2(1, 1);
Build(1, n, 1);
int q; scanf("%d",&q);
char s[20];
while(q --){
int x;
scanf("%s",s);
scanf("%d",&x); x += 1;
if(s[0] == 'i'){
int temp = qRange(1, x);
updRange(1, x, 1);
int res = qRange(1, x) - temp;
printf("%d\n",res);
}
else{
int res = qSon(x);
updSon(x, 0);
printf("%d\n",res);
}
// for(int i = 1; i <= n; ++ i){
// cout<<tree[tpp[i]].val<<" ";
// }
// cout<<endl;
}
return 0;
}
P3178 HAOI2015]树上操作
/*
2020/8/19/8:40
*/
#include<bits/stdc++.h>
using namespace std;
#define rep(i, a, n) for(int i = a; i <= n; ++ i);
#define per(i, a, n) for(int i = n; i >= a; -- i);
typedef long long ll;
const int N = 2e6+ 5;
// const ll mod = 1e9 + 7;
int mod;
const double Pi = acos(- 1.0);
const int INF = 0x3f3f3f3f;
const int G = 3, Gi = 332748118;
ll qpow(ll a, ll b) { ll res = 1; while(b){ if(b & 1) res = (res * a) % mod; a = (a * a) % mod; b >>= 1;} return res; }
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
ll lcm(ll a, ll b) { return a * b / gcd(a, b);}
bool cmp(int a, int b){ return a > b;}
//
int tpp[N];
int n, m, r;
int head[N], cnt = 0;
struct node{
int to, nxt, c;
}edge[N << 1];
struct Tree{
int l, r; ll val, lz;
}tree[N * 4];
int val[N], tval[N];
int son[N], siz[N],dfn[N], dep[N], top[N], fa[N], rnk[N];
int res = 0, tot = 0;
void add(int u, int v){
edge[cnt].to = v, edge[cnt].nxt = head[u], head[u] = cnt ++;
edge[cnt].to = u, edge[cnt].nxt = head[v], head[v] = cnt ++;
}
void pushdown(int index){
if(tree[index].lz){
ll temp = tree[index].lz;
tree[index].lz = 0;
tree[index << 1].val += (tree[index << 1].r - tree[index << 1].l + 1) * temp;
tree[index << 1 | 1].val += (tree[index<<1|1].r - tree[index<<1|1].l + 1) * temp;
tree[index << 1].lz += temp;
tree[index << 1 | 1].lz += temp;
}
}
void pushup(int index){
tree[index].val = tree[index << 1].val + tree[index << 1 | 1].val;
}
void Build(int l, int r, int index){
tree[index].l = l, tree[index].r = r;
tree[index].lz = 0;
if(l == r){
tree[index].val = tval[l];
tpp[l] = index;
return;
}
int mid = (l + r) >> 1;
Build(l, mid, index << 1);
Build(mid + 1, r, index << 1 | 1);
pushup(index);
}
void updata(int l, int r, int index, int val){
if(tree[index].l >= l && tree[index].r <= r){
tree[index].lz += val;
tree[index].val += (ll)val * (tree[index].r - tree[index].l + 1);
return;
}
pushdown(index);
int mid = (tree[index].l + tree[index].r) >> 1;
if(l <= mid) updata(l, r, index << 1, val);
if(r > mid) updata(l, r, index << 1 | 1, val);
pushup(index);
}
ll query(int l, int r, int index){
if(l <= tree[index].l && tree[index].r <= r){
return tree[index].val;
}
pushdown(index);
int mid = (tree[index].l + tree[index].r) >> 1;
ll ans = 0;
if(l <= mid) ans += query(l, r, index << 1);
if(r > mid) ans += query(l, r, index << 1 | 1);
return ans;
}
// --------------------------------
void Change(int x, int val){
updata(dfn[x], dfn[x], 1, val);
}
void Add(int x, int val){
updata(dfn[x], dfn[x] + siz[x] - 1, 1, val);
}
ll Qsol(int x, int y){
ll ans = 0;
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]]) swap(x, y);
ans += query(dfn[top[x]], dfn[x], 1);
x = fa[top[x]];
}
if(dep[x] > dep[y]) swap(x, y);
ans += query(dfn[x], dfn[y], 1);
return ans;
}
void dfs1(int u, int pre){
dep[u] = dep[pre] + 1;
fa[u] = pre;
siz[u] = 1;
int maxx = -1;
for(int i = head[u]; i != -1; i = edge[i].nxt){
int v = edge[i].to;
if(v == pre) continue;
dfs1(v, u);
siz[u] += siz[v];
if(siz[v] > maxx){
maxx = siz[v];
son[u] = v;
}
}
}
void dfs2(int u, int topu){ //topu当前链的最顶端的节点
dfn[u] = ++ tot;
tval[tot] = val[u];
top[u] = topu;
rnk[tot] = u;
if(!son[u]) return;
dfs2(son[u], topu);
for(int i = head[u]; i != -1; i = edge[i].nxt){
int v = edge[i].to;
if(v == son[u] || v == fa[u]) continue;
dfs2(v, v);
}
}
// void print(){
// for(int i = 1; i <= n; ++ i){
// int tt = tpp[dfn[i]];
// cout<<tree[tt].val<<" ";
// }
// cout<<endl;
// }
int main()
{
scanf("%d%d",&n,&m);
cnt = 0;
for(int i = 0; i <= n; ++ i) head[i] = -1;
for(int i = 1; i <= n; ++ i) scanf("%d",&val[i]);
for(int i = 1; i < n; ++ i){
int x, y; scanf("%d%d",&x,&y);
add(x, y);
}
dfs1(1, 0);
dfs2(1, 1);
Build(1, n, 1);
// print();
int op;
while(m --){
scanf("%d",&op);
if(op == 1){
int x, y; scanf("%d%d",&x,&y);
Change(x, y);
}
else if(op == 2){
int x, y; scanf("%d%d",&x,&y);
Add(x, y);
}
else{
int x; scanf("%d",&x);
printf("%lld\n",Qsol(x, 1));
}
// print();
}
return 0;
}
P3950 部落冲突
/*
P3950
树链剖分
2020/8/19/9:15
*/
#include<bits/stdc++.h>
using namespace std;
#define rep(i, a, n) for(int i = a; i <= n; ++ i);
#define per(i, a, n) for(int i = n; i >= a; -- i);
typedef long long ll;
const int N = 2e6+ 5;
// const ll mod = 1e9 + 7;
int mod;
const double Pi = acos(- 1.0);
const int INF = 0x3f3f3f3f;
const int G = 3, Gi = 332748118;
ll qpow(ll a, ll b) { ll res = 1; while(b){ if(b & 1) res = (res * a) % mod; a = (a * a) % mod; b >>= 1;} return res; }
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
ll lcm(ll a, ll b) { return a * b / gcd(a, b);}
bool cmp(int a, int b){ return a > b;}
//
// int tpp[N];
int n, m, r;
int head[N], cnt = 0;
struct node{
int to, nxt, c;
}edge[N << 1];
struct Tree{
int l, r, val, lz;
}tree[N * 4];
int val[N], tval[N];
int son[N], siz[N],dfn[N], dep[N], top[N], fa[N], rnk[N];
int res = 0, tot = 0;
void add(int u, int v){
edge[cnt].to = v, edge[cnt].nxt = head[u], head[u] = cnt ++;
edge[cnt].to = u, edge[cnt].nxt = head[v], head[v] = cnt ++;
}
void pushdown(int index){
if(tree[index].lz){
int temp = tree[index].lz;
tree[index].lz = 0;
tree[index << 1].val = temp;
tree[index << 1 | 1].val = temp;
tree[index << 1].lz = temp;
tree[index << 1 | 1].lz = temp;
}
}
void pushup(int index){
if(tree[index << 1].val || tree[index << 1 | 1].val) tree[index].val = 1;
else tree[index].val = 0;
}
void Build(int l, int r, int index){
tree[index].l = l, tree[index].r = r;
tree[index].lz = 0;
if(l == r){
tree[index].val = 0;
// tpp[l] = index;
return;
}
int mid = (l + r) >> 1;
Build(l, mid, index << 1);
Build(mid + 1, r, index << 1 | 1);
pushup(index);
}
void updata(int l, int r, int index, int val){
if(tree[index].l >= l && tree[index].r <= r){
tree[index].lz = val;
tree[index].val = val;
return;
}
pushdown(index);
int mid = (tree[index].l + tree[index].r) >> 1;
if(l <= mid) updata(l, r, index << 1, val);
if(r > mid) updata(l, r, index << 1 | 1, val);
pushup(index);
}
int query(int l, int r, int index){
if(l <= tree[index].l && tree[index].r <= r){
return tree[index].val;
}
pushdown(index);
int mid = (tree[index].l + tree[index].r) >> 1;
ll ans = 0;
if(l <= mid) ans += query(l, r, index << 1);
if(r > mid) ans += query(l, r, index << 1 | 1);
return ans > 0 ? 1 : 0;
}
// --------------------------------
void Csol(int x, int y){
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]]) swap(x, y);
updata(dfn[top[x]], dfn[x], 1, 1);
x = fa[top[x]];
}
if(dep[x] > dep[y]) swap(x, y);
updata(dfn[x] + 1, dfn[y], 1, 1);
}
void Usol(int x, int y){
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]]) swap(x, y);
updata(dfn[top[x]], dfn[x], 1, 0);
x = fa[top[x]];
}
if(dep[x] > dep[y]) swap(x, y);
updata(dfn[x] + 1, dfn[y], 1, 0);
}
int Qsol(int x, int y){
int ans = 0;
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]]) swap(x, y);
ans += query(dfn[top[x]], dfn[x], 1);
x = fa[top[x]];
}
if(dep[x] > dep[y]) swap(x, y);
ans += query(dfn[x] + 1, dfn[y], 1);
return ans != 0;
}
void dfs1(int u, int pre){
dep[u] = dep[pre] + 1;
fa[u] = pre;
siz[u] = 1;
int maxx = -1;
for(int i = head[u]; i != -1; i = edge[i].nxt){
int v = edge[i].to;
if(v == pre) continue;
dfs1(v, u);
siz[u] += siz[v];
if(siz[v] > maxx){
maxx = siz[v];
son[u] = v;
}
}
}
void dfs2(int u, int topu){ //topu当前链的最顶端的节点
dfn[u] = ++ tot;
tval[tot] = val[u];
top[u] = topu;
rnk[tot] = u;
if(!son[u]) return;
dfs2(son[u], topu);
for(int i = head[u]; i != -1; i = edge[i].nxt){
int v = edge[i].to;
if(v == son[u] || v == fa[u]) continue;
dfs2(v, v);
}
}
// void print(){
// for(int i = 1; i <= n; ++ i){
// int tt = tpp[dfn[i]];
// cout<<tree[tt].val;
// }
// cout<<endl;
// }
int ax[N], ay[N], cnum = 0;
int main()
{
scanf("%d%d",&n,&m);
cnt = 0;
for(int i = 0; i <= n; ++ i) head[i] = -1;
for(int i = 1; i < n; ++ i){
int x, y; scanf("%d%d",&x,&y);
add(x, y);
}
dfs1(1, 0);
dfs2(1, 1);
Build(1, n, 1);
char op[5];
while(m --){
scanf("%s",op);
if(op[0] == 'C'){
int x, y; scanf("%d%d",&x,&y);
ax[++ cnum] = x, ay[cnum] = y;
Csol(x, y);
}
else if(op[0] == 'U'){
int x; scanf("%d",&x);
Usol(ax[x], ay[x]);
}
else{
int x, y; scanf("%d%d",&x,&y);
if(Qsol(x, y)) printf("No\n");
else printf("Yes\n");
}
}
return 0;
}
P4114 Qtree1
/*
P4114
树链剖分
2020/8/19/9:41
*/
#include<bits/stdc++.h>
using namespace std;
#define rep(i, a, n) for(int i = a; i <= n; ++ i);
#define per(i, a, n) for(int i = n; i >= a; -- i);
typedef long long ll;
const int N = 2e6+ 5;
// const ll mod = 1e9 + 7;
int mod;
const double Pi = acos(- 1.0);
const int INF = 0x3f3f3f3f;
const int G = 3, Gi = 332748118;
ll qpow(ll a, ll b) { ll res = 1; while(b){ if(b & 1) res = (res * a) % mod; a = (a * a) % mod; b >>= 1;} return res; }
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
ll lcm(ll a, ll b) { return a * b / gcd(a, b);}
bool cmp(int a, int b){ return a > b;}
//
int tpp[N];
int n, m, r;
int head[N], cnt = 0;
struct node{
int to, nxt, c;
}edge[N << 1];
struct Tree{
int l, r, val, lz;
}tree[N * 4];
int val[N], tval[N];
int son[N], siz[N],dfn[N], dep[N], top[N], fa[N], rnk[N];
int res = 0, tot = 0;
void add(int u, int v, int w){
edge[cnt].to = v, edge[cnt].c = w, edge[cnt].nxt = head[u], head[u] = cnt ++;
edge[cnt].to = u, edge[cnt].c = w, edge[cnt].nxt = head[v], head[v] = cnt ++;
}
void pushdown(int index){
if(tree[index].lz){
int temp = tree[index].lz;
tree[index].lz = 0;
tree[index << 1].val = temp;
tree[index << 1 | 1].val = temp;
tree[index << 1].val = temp;
tree[index << 1 | 1].val = temp;
}
}
void pushup(int index){
tree[index].val = max(tree[index << 1].val, tree[index << 1 | 1].val);
}
void Build(int l, int r, int index){
tree[index].l = l, tree[index].r = r;
tree[index].lz = 0;
if(l == r){
tree[index].val = tval[l];
tpp[l] = index;
return;
}
int mid = (l + r) >> 1;
Build(l, mid, index << 1);
Build(mid + 1, r, index << 1 | 1);
pushup(index);
}
void updata(int l, int r, int index, int val){
if(tree[index].l >= l && tree[index].r <= r){
tree[index].lz = val;
tree[index].val = val;
return;
}
pushdown(index);
int mid = (tree[index].l + tree[index].r) >> 1;
if(l <= mid) updata(l, r, index << 1, val);
if(r > mid) updata(l, r, index << 1 | 1, val);
pushup(index);
}
int query(int l, int r, int index){
if(l <= tree[index].l && tree[index].r <= r){
return tree[index].val;
}
pushdown(index);
int mid = (tree[index].l + tree[index].r) >> 1;
int ans = 0;
if(l <= mid) ans = max(ans, query(l, r, index << 1));
if(r > mid) ans = max(ans, query(l, r, index << 1 | 1));
return ans;
}
// --------------------------------
void Csol(int x, int y, int val){
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]]) swap(x, y);
updata(dfn[top[x]], dfn[x], 1, val);
x = fa[top[x]];
}
if(dep[x] > dep[y]) swap(x, y);
updata(dfn[x] + 1, dfn[y], 1, val);
}
int Qsol(int x, int y){
int ans = 0;
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]]) swap(x, y);
ans = max(ans, query(dfn[top[x]], dfn[x], 1));
x = fa[top[x]];
}
if(dep[x] > dep[y]) swap(x, y);
ans = max(ans, query(dfn[x] + 1, dfn[y], 1));
return ans;
}
void dfs1(int u, int pre){
dep[u] = dep[pre] + 1;
fa[u] = pre;
siz[u] = 1;
int maxx = -1;
for(int i = head[u]; i != -1; i = edge[i].nxt){
int v = edge[i].to, w = edge[i].c;
if(v == pre) continue;
val[v] = w;
dfs1(v, u);
siz[u] += siz[v];
if(siz[v] > maxx){
maxx = siz[v];
son[u] = v;
}
}
}
void dfs2(int u, int topu){ //topu当前链的最顶端的节点
dfn[u] = ++ tot;
tval[tot] = val[u];
top[u] = topu;
rnk[tot] = u;
if(!son[u]) return;
dfs2(son[u], topu);
for(int i = head[u]; i != -1; i = edge[i].nxt){
int v = edge[i].to;
if(v == son[u] || v == fa[u]) continue;
dfs2(v, v);
}
}
// void print(){
// for(int i = 1; i <= n; ++ i){
// int tt = tpp[dfn[i]];
// cout<<tree[tt].val<<" ";
// }
// cout<<endl;
// }
int ax[N], ay[N];
int main()
{
scanf("%d",&n);
cnt = 0;
for(int i = 0; i <= n; ++ i) head[i] = -1;
for(int i = 1; i < n; ++ i){
int z; scanf("%d%d%d",&ax[i],&ay[i],&z);
add(ax[i], ay[i], z);
}
dfs1(1, 0);
dfs2(1, 1);
Build(1, n, 1);
char op[10];
while(1){
scanf("%s",op);
if(op[0] == 'D') break;
else if(op[0] == 'C'){
int x, y; scanf("%d%d",&x,&y);
Csol(ax[x], ay[x], y);
}
else{
int x, y; scanf("%d%d",&x,&y);
if(x == y) printf("0\n");
else printf("%d\n",Qsol(x, y));
}
}
return 0;
}
P4116 Qtree3
/*
P4116
2020/8/19/9:47
树链剖分
*/
#include<bits/stdc++.h>
using namespace std;
#define rep(i, a, n) for(int i = a; i <= n; ++ i);
#define per(i, a, n) for(int i = n; i >= a; -- i);
typedef long long ll;
const int N = 2e6+ 5;
const ll mod = 1e9 + 7;
const double Pi = acos(- 1.0);
const int INF = 0x3f3f3f3f;
const int G = 3, Gi = 332748118;
ll qpow(ll a, ll b) { ll res = 1; while(b){ if(b & 1) res = (res * a) % mod; a = (a * a) % mod; b >>= 1;} return res; }
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
ll lcm(ll a, ll b) { return a * b / gcd(a, b);}
bool cmp(int a, int b){ return a > b;}
//
int n, m, r;
int head[N], cnt = 0;
struct node{
int to, nxt, c;
}edge[N << 1];
struct Tree{
int l, r, val, lz;
}tree[N * 4];
int val[N], tval[N];
int son[N], siz[N],dfn[N], dep[N], top[N], fa[N], rnk[N];
int res = 0, tot = 0;
void add(int u, int v){
edge[cnt].to = v, edge[cnt].nxt = head[u], head[u] = cnt ++;
edge[cnt].to = u, edge[cnt].nxt = head[v], head[v] = cnt ++;
}
void pushup(int index){
tree[index].val = min(tree[index << 1].val , tree[index << 1 | 1].val);
}
void Build(int l, int r, int index){
tree[index].l = l, tree[index].r = r;
tree[index].lz = 0;
if(l == r){
tree[index].val = INF;
return;
}
int mid = (l + r) >> 1;
Build(l, mid, index << 1);
Build(mid + 1, r, index << 1 | 1);
pushup(index);
}
void updata(int l, int r, int index, int val){
if(tree[index].l == tree[index].r){
if(tree[index].val == INF) tree[index].val = val;
else tree[index].val = INF;
return;
}
int mid = (tree[index].l + tree[index].r) >> 1;
if(l <= mid) updata(l, r, index << 1, val);
if(r > mid) updata(l, r, index << 1 | 1, val);
pushup(index);
}
int query(int l, int r, int index){
if(l <= tree[index].l && tree[index].r <= r){
return tree[index].val;
}
int mid = (tree[index].l + tree[index].r) >> 1;
int ans = INF;
if(r > mid) ans = min(ans, query(l, r, index << 1 | 1));
if(l <= mid) ans = min(ans, query(l, r, index << 1));
return ans;
}
// --------------------------------
int qRange(int x, int y){ //x 到 y树上最短路径结点权值和
int res = INF;
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]]) swap(x, y);
res = min(res, query(dfn[top[x]], dfn[x], 1));
x = fa[top[x]];
}
if(dep[x] > dep[y]) swap(x, y);
res = min(res, query(dfn[x], dfn[y], 1));
return res;
}
void dfs1(int u, int pre){
dep[u] = dep[pre] + 1;
fa[u] = pre;
siz[u] = 1;
int maxx = -1;
for(int i = head[u]; i != -1; i = edge[i].nxt){
int v = edge[i].to;
if(v == pre) continue;
dfs1(v, u);
siz[u] += siz[v];
if(siz[v] > maxx){
maxx = siz[v];
son[u] = v;
}
}
}
void dfs2(int u, int topu){ //topu当前链的最顶端的节点
dfn[u] = ++ tot;
top[u] = topu;
rnk[tot] = u;
if(!son[u]) return;
dfs2(son[u], topu);
for(int i = head[u]; i != -1; i = edge[i].nxt){
int v = edge[i].to;
if(v == son[u] || v == fa[u]) continue;
dfs2(v, v);
}
}
int main()
{
scanf("%d%d",&n,&m);
cnt = 0;
for(int i = 0; i <= n; ++ i) head[i] = -1;
for(int i = 1; i < n; ++ i){
int x, y; scanf("%d%d",&x,&y);
add(x, y);
}
dfs1(1, 0);
dfs2(1, 1);
Build(1, n, 1);
int op;
while(m --){
int x; scanf("%d%d",&op,&x);
if(op == 0){
updata(dfn[x], dfn[x], 1, dfn[x]);
}
else{
int tt = qRange(1, x);
if(tt != INF) printf("%d\n",rnk[tt]);
else printf("-1\n");
}
}
return 0;
}
P3401 洛谷树
P1505 国家集训队]旅游
P3250 HNOI2016]网络