声明:由于本人能力尚不优 故无法做出解释文章 此文仅为自己日记 感谢你的阅读
作为队里的数据结构选手 2019西安邀请赛的E题 竟然在有机时的情况下 想到了线段树log^2的拆位做法 但是题目路径把自己问懵逼了 啥? 啥是最短路? 点和点之间最短路是啥?
于是 这名数据结构小菜鸡只好回来恶补某个维护树上点和点直接最短路的东西 ---- 叔脸剖分(这名数据结构小菜鸡没脸啦

ZJOI2008 树的统计

我们只要维护一下一个max 和 sum 即可轻松AC

/*if you can't see the repayWhy not just work step by steprubbish is relaxedto ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
//#pragma comment(linker, "/STACK:10240000,10240000")
using namespace std;#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))typedef pair<int,int> pll;
typedef long long ll;
typedef unsigned long long ull;
const ull hash1 = 201326611;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod =  (int)1e9+7;ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
//ull ha[MAX_N],pp[MAX_N];inline int read()
{int date = 0,m = 1; char ch = 0;while(ch!='-'&&(ch<'0'|ch>'9'))ch = getchar();if(ch=='-'){m = -1; ch = getchar();}while(ch>='0' && ch<='9'){date = date*10+ch-'0';ch = getchar();}return date*m;
}
const int MAX_N = 30025;
int arr[MAX_N],p[MAX_N],top[MAX_N],eid,cnt,Rank[MAX_N],id[MAX_N],sz[MAX_N],son[MAX_N],maxx[MAX_N<<2],s[MAX_N<<2],depth[MAX_N],fa[MAX_N];
int n;
void init()
{memset(p,-1,sizeof(p));eid = 0;
}
struct edge
{int v,next;
}e[MAX_N<<1];
void add(int u,int v)
{e[eid].v =v ;e[eid].next = p[u];p[u] = eid++;
}
int Max(int a,int b){return a > b?a:b;}
void up(int rt)
{maxx[rt] = Max(maxx[rt<<1],maxx[rt<<1|1]);s[rt] = s[rt<<1]+s[rt<<1|1];
}
void build(int rt,int l,int r)
{if(l==r){s[rt] = maxx[rt] = arr[Rank[l]];return;}int mid = (l+r)>>1;build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);up(rt);
}
void update(int rt,int l,int r,int x,int v)
{if(l==r){maxx[rt] = s[rt] = v;return;}int mid = (l+r)>>1;if(x<=mid) update(rt<<1,l,mid,x,v);else update(rt<<1|1,mid+1,r,x,v);up(rt);
}
int query(int rt,int l,int r,int x,int y,int flag)
{if(x<=l&&r<=y){if(flag==0) return maxx[rt];return s[rt];}int mid = (l+r)>>1;if(x>mid) return query(rt<<1|1,mid+1,r,x,y,flag);else if(y<=mid) return query(rt<<1,l,mid,x,y,flag);else{if(flag==0) return Max(query(rt<<1,l,mid,x,y,flag),query(rt<<1|1,mid+1,r,x,y,flag));return query(rt<<1,l,mid,x,y,flag)+query(rt<<1|1,mid+1,r,x,y,flag);}
}
void dfs1(int x,int fath)
{fa[x] = fath;depth[x] = depth[fath]+1;sz[x] = 1;for(int i = p[x];i+1;i=e[i].next){int v = e[i].v;if(v==fath) continue;dfs1(v,x);sz[x]+=sz[v];if(sz[son[x]]<sz[v]) son[x] = v;}
}
void dfs2(int u,int t)
{top[u] = t;id[u] = ++cnt;Rank[cnt] = u;if(!son[u]) return;dfs2(son[u],t);for(int i = p[u];i+1;i=e[i].next){int  v= e[i].v;if(v!=son[u]&&v!=fa[u]) dfs2(v,v);}
}
int Sum(int x,int y)
{int ans = 0;while(top[x]!=top[y]){if(depth[top[x]]<depth[top[y]]) swap(x,y);ans+=query(1,1,n,id[top[x]],id[x],1);x = fa[top[x]];}if(id[x]>id[y]) swap(x,y);ans+=query(1,1,n,id[x],id[y],1);return ans;
}
int sum(int x,int y)
{int ans = -30001;while(top[x]!=top[y]){if(depth[top[x]]<depth[top[y]]) swap(x,y);ans = Max(ans,query(1,1,n,id[top[x]],id[x],0));x = fa[top[x]];}if(id[x]>id[y]) swap(x,y);ans = Max(ans,query(1,1,n,id[x],id[y],0));return ans;
}
/*namespace sgt
{#define mid ((l+r)>>1)#undef mid
}*//*int root[MAX_N],cnt,sz;
namespace hjt
{#define mid ((l+r)>>1)struct node{int l,r,maxx;}T[MAX_N*40];#undef mid
}*/int main()
{//ios::sync_with_stdio(false);//freopen("a.txt","r",stdin);//freopen("b.txt","w",stdout);int a,b,m,x,y;n = read();char opt[25];init();for(int i = 1;i<n;++i){a = read();b=read();add(a,b);add(b,a);}for(int i = 1;i<=n;++i) arr[i] = read();dfs1(1,0);dfs2(1,1);build(1,1,n);m = read();for(int i = 1;i<=m;++i){scanf("%s",opt);if(opt[0]=='C'){x = read();y=read();update(1,1,n,id[x],y);}else{if(opt[1]=='M'){x = read();y = read();printf("%d\n",sum(x,y));}else{x = read();y=read();printf("%d\n",Sum(x,y));}}}//fclose(stdin);//fclose(stdout);//cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;return 0;
}

cogs1612

用到了树链剖分的第一个dfs序 因为dfs序是连续的 你记得用小的-1 而不是大的dfn 因为这两个父子可能不相连 举个例子 父亲的右儿子 因为这个WA了一发

//http://cogs.pro:8080/cogs/problem/problem.php?pid=vXNzykekV
/*if you can't see the repayWhy not just work step by steprubbish is relaxedto ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
//#pragma comment(linker, "/STACK:10240000,10240000")
using namespace std;#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))typedef pair<int,int> pll;
typedef long long ll;
typedef unsigned long long ull;
const ull hash1 = 201326611;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod =  (int)1e9+7;ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
//ull ha[MAX_N],pp[MAX_N];inline int read()
{int date = 0,m = 1; char ch = 0;while(ch!='-'&&(ch<'0'|ch>'9'))ch = getchar();if(ch=='-'){m = -1; ch = getchar();}while(ch>='0' && ch<='9'){date = date*10+ch-'0';ch = getchar();}return date*m;
}
const int MAX_N = 100025;
int a[MAX_N],b[MAX_N],p[MAX_N],eid,cnt,low[MAX_N],sz[MAX_N],depth[MAX_N],Rank[MAX_N],Point[MAX_N],high[MAX_N];
ll arr[MAX_N];
ll Max(ll a,ll b) {return a>b?a:b;}
ll Min(ll a,ll b) {return a<b?a:b;}
void init()
{memset(p,-1,sizeof(p));eid = 0;
}
struct edge
{int next,v,d;
}e[MAX_N<<1];
void add(int u,int v,int d)
{e[eid].d = d;e[eid].v = v;e[eid].next = p[u];p[u] = eid++;
}
void dfs(int x,int fa)
{sz[x] = 1;depth[x] = depth[fa]+1;low[x] = ++cnt;Rank[cnt] = x;for(int i = p[x];i+1;i=e[i].next){int v  = e[i].v;if(v==fa) continue;Point[e[i].d] = v;dfs(v,x);sz[x]+=sz[v];}high[x] = cnt;
}namespace sgt
{#define mid ((l+r)>>1)ll maxx[MAX_N<<2],minn[MAX_N<<2];void up(int rt){maxx[rt] = Max(maxx[rt<<1],maxx[rt<<1|1]);minn[rt] = Min(minn[rt<<1],minn[rt<<1|1]);}void build(int rt,int l,int r){if(l==r){maxx[rt] = minn[rt] = arr[Rank[l]];return;}build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);up(rt);}void update(int rt,int l,int r,int x,int v){if(l==r){maxx[rt] = minn[rt] = v;return;}if(x<=mid) update(rt<<1,l,mid,x,v);else update(rt<<1|1,mid+1,r,x,v);up(rt);}ll query(int rt,int l,int r,int x,int y,int flag){if(x>y) if(flag==0) return 0;else return 100000005ll;if(x<=l&&r<=y){if(flag==0) return maxx[rt];return minn[rt];}if(x>mid) return query(rt<<1|1,mid+1,r,x,y,flag);else if(y<=mid) return query(rt<<1,l,mid,x,y,flag);else{if(flag==0) return Max(query(rt<<1,l,mid,x,y,flag),query(rt<<1|1,mid+1,r,x,y,flag));return Min(query(rt<<1,l,mid,x,y,flag),query(rt<<1|1,mid+1,r,x,y,flag));}}#undef mid
}/*int root[MAX_N],cnt,sz;
namespace hjt
{#define mid ((l+r)>>1)struct node{int l,r,maxx;}T[MAX_N*40];#undef mid
}*/int main()
{//ios::sync_with_stdio(false);freopen("westward.in","r",stdin);freopen("westward.out","w",stdout);int x,y,n,Q;char opt[25];n = read();Q = read();for(int i = 1;i<=n;++i) scanf("%lld",&arr[i]);init();for(int i = 1;i<n;++i){a[i] = read();b[i] = read();add(a[i],b[i],i);add(b[i],a[i],i);}dfs(1,0);sgt::build(1,1,n);for(int i = 1;i<=Q;++i){scanf("%s",opt);if(opt[0]=='Q'){x =  read();ll maxx1,maxx2,minn1,minn2;int P = a[x],P_ = b[x];if(low[P]>low[P_]) swap(P,P_);maxx1 = Max(sgt::query(1,1,n,1,low[P_]-1,0),sgt::query(1,1,n,high[P_]+1,n,0));minn1 = Min(sgt::query(1,1,n,1,low[P_]-1,1),sgt::query(1,1,n,high[P_]+1,n,1));maxx2 = sgt::query(1,1,n,low[P_],high[P_],0);minn2 = sgt::query(1,1,n,low[P_],high[P_],1);printf("%lld\n",minn1*maxx1+minn2*maxx2);}else{x = read();y= read();sgt::update(1,1,n,low[x],y);}}//fclose(stdin);//fclose(stdout);//cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;return 0;
}

BZOJ2243
这题数颜色 大家是不是对线段树统计颜色部分都会
然后为了让我们好写 我们顺便用树链剖分维护一下lca
这样你就不用swap 因为你一旦swap 颜色左右必须要考虑
你考虑两个点各自到lca 因为从底向上 所以不用swap

/*if you can't see the repayWhy not just work step by steprubbish is relaxedto ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
//#pragma comment(linker, "/STACK:10240000,10240000")
using namespace std;#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))typedef pair<int,int> pll;
typedef long long ll;
typedef unsigned long long ull;
const ull hash1 = 201326611;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod =  (int)1e9+7;ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
//ull ha[MAX_N],pp[MAX_N];inline int read()
{int date = 0,m = 1; char ch = 0;while(ch!='-'&&(ch<'0'|ch>'9'))ch = getchar();if(ch=='-'){m = -1; ch = getchar();}while(ch>='0' && ch<='9'){date = date*10+ch-'0';ch = getchar();}return date*m;
}/*namespace sgt
{#define mid ((l+r)>>1)#undef mid
}*//*int root[MAX_N],cnt,sz;
namespace hjt
{#define mid ((l+r)>>1)struct node{int l,r,maxx;}T[MAX_N*40];#undef mid
}*/
const int MAX_N = 100025;
int n,cnt,s[MAX_N<<2],rnum[MAX_N<<2],lnum[MAX_N<<2],col[MAX_N<<2],p[MAX_N],eid ,fa[MAX_N],sz[MAX_N],depth[MAX_N],son[MAX_N],Rank[MAX_N],top[MAX_N],id[MAX_N],arr[MAX_N];
void init()
{memset(p,-1,sizeof(p));eid = 0;
}
void up(int rt)
{lnum[rt] = lnum[rt<<1];rnum[rt] = rnum[rt<<1|1];if(lnum[rt<<1|1]==rnum[rt<<1]) s[rt] = s[rt<<1]+s[rt<<1|1]-1;else s[rt] = s[rt<<1] +s[rt<<1|1];
}
void build(int rt,int l,int r)
{col[rt] = lnum[rt] = rnum[rt] = -1;s[rt] = 0;if(l==r){lnum[rt] = rnum[rt] = arr[Rank[l]];s[rt] = 1;return ;}int mid = (l+r)>>1;build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);up(rt);
}
void down(int rt,int l,int r)
{if(col[rt]!=-1){col[rt<<1] = col[rt<<1|1] = col[rt];s[rt<<1] = s[rt<<1|1] = 1;lnum[rt<<1] = lnum[rt<<1|1] = rnum[rt<<1] = rnum[rt<<1|1] = col[rt];col[rt] = -1;}
}
void update(int rt,int l,int r,int x,int y,int v)
{if(x<=l&&r<=y){lnum[rt] = rnum[rt] = col[rt] = v;s[rt] = 1;return ;}down(rt,l,r);int mid = (l+r)>>1;if(x>mid) update(rt<<1|1,mid+1,r,x,y,v);else if(y<=mid) update(rt<<1,l,mid,x,y,v);else update(rt<<1,l,mid,x,y,v),update(rt<<1|1,mid+1,r,x,y,v);up(rt);
}
int query(int rt,int l,int r,int x,int y)
{if(x<=l&&r<=y){return s[rt];}int mid = (l+r)>>1;down(rt,l,r);if(x>mid) return query(rt<<1|1,mid+1,r,x,y);else if(y<=mid) return query(rt<<1,l,mid,x,y);else{if(lnum[rt<<1|1]==rnum[rt<<1]) return (query(rt<<1,l,mid,x,y)+query(rt<<1|1,mid+1,r,x,y) - 1);else return (query(rt<<1,l,mid,x,y)+query(rt<<1|1,mid+1,r,x,y));}
}
struct edge
{int v,next;
}e[MAX_N<<1];
void add(int u,int v)
{e[eid].v =v;e[eid].next = p[u];p[u] = eid++;
}
void dfs1(int x,int fath)
{sz[x] = 1;depth[x] = depth[fath]+1;fa[x] = fath;for(int i = p[x];i+1;i=e[i].next){int v = e[i].v;if(v==fath) continue;dfs1(v,x);sz[x]+=sz[v];if(sz[v]>sz[son[x]]) son[x] = v;}
}
void dfs2(int u,int t)
{top[u] = t;id[u] = ++cnt;Rank[cnt] = u;if(!son[u])return;dfs2(son[u],t);for(int i = p[u];i+1;i=e[i].next){int v = e[i].v;if(v!=son[u]&&v!=fa[u])dfs2(v,v);}
}
void updates(int x,int y,int c)
{while(top[x]!=top[y]){if(depth[top[x]]<depth[top[y]])swap(x,y);update(1,1,n,id[top[x]],id[x],c);x = fa[top[x]];}if(id[x]>id[y])swap(x,y);update(1,1,n,id[x],id[y],c);
}
int getl(int rt,int l,int r,int x)
{if(l==r){return lnum[rt];}int mid = (l+r)>>1;down(rt,l,r);if(x<=mid) return getl(rt<<1,l,mid,x);else return getl(rt<<1|1,mid+1,r,x);
}
inline int lca(int x,int y){int f1=top[x],f2=top[y];while(f1!=f2) {if(depth[f1]<depth[f2]) swap(f1,f2),swap(x,y);x=fa[f1]; f1=top[x];}if(depth[x]<depth[y]) swap(x,y);return y;
}
int sum(int x,int y)
{int ans = 0,last = -1,now = -1;while(top[x]!=top[y]){now = getl(1,1,n,id[x]);ans += query(1,1,n,id[top[x]],id[x]);if(now==last) ans--;last = getl(1,1,n,id[top[x]]);x = fa[top[x]];}ans+=query(1,1,n,id[y],id[x]);now = getl(1,1,n,id[x]);if(now==last) ans--;return ans;
}
int main()
{//ios::sync_with_stdio(false);//freopen("a.txt","r",stdin);//freopen("b.txt","w",stdout);int m,a,b,x,y,v;char opt[5];n = read();m = read();init();for(int i = 1;i<=n;++i) arr[i] = read();for(int i = 1;i<n;++i){a = read();b=read();add(a,b);add(b,a);}dfs1(1,0);dfs2(1,1);build(1,1,n);for(int i = 1;i<=m;++i){scanf("%s",opt);if(opt[0]=='C'){x = read();y=read();v=read();updates(x,y,v);}else{x = read();y = read();int LCA = lca(x,y);int ans = sum(x,LCA)+sum(y,LCA);printf("%d\n",ans-1);}}//fclose(stdin);//fclose(stdout);//cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;return 0;
}

BZOJ4538
这题应该是我目前熟练剖分做过最难的题了
我们需要维护的是 不经过某段路径的最大值 然后用两个堆
压入堆 和删除堆 删除就是看两个堆顶是不是相同
否则输出压入堆的堆顶
注意 维护的是是不经过某段路径的最大值 这样你在问就可以直接问出来了

/*if you can't see the repayWhy not just work step by steprubbish is relaxedto ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
//#pragma comment(linker, "/STACK:10240000,10240000")
using namespace std;#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))typedef pair<int,int> pll;
typedef long long ll;
typedef unsigned long long ull;
const ull hash1 = 201326611;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod =  (int)1e9+7;ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
//ull ha[MAX_N],pp[MAX_N];inline int read()
{int date = 0,m = 1; char ch = 0;while(ch!='-'&&(ch<'0'|ch>'9'))ch = getchar();if(ch=='-'){m = -1; ch = getchar();}while(ch>='0' && ch<='9'){date = date*10+ch-'0';ch = getchar();}return date*m;
}
const int MAX_N = 100011;
const int MAX_M = 200011;
int fa[MAX_N],sz[MAX_N],depth[MAX_N],son[MAX_N],top[MAX_N],id[MAX_N],p[MAX_N],eid,n,ans,cnt;
void init()
{memset(p,-1,sizeof(p));eid = 0;
}
struct edge
{int v,next;
}e[MAX_N<<1];
void add(int u,int v)
{e[eid].v = v;e[eid].next = p[u];p[u] = eid++;
}
struct priority_tree
{priority_queue<int> q1,q2;inline void push1(int x) {q1.push(x);}inline void push2(int x) {q2.push(x);}inline int top(){int res = -1;while(!q2.empty()&&(q1.top()==q2.top())) q1.pop(),q2.pop();if(!q1.empty()) res = q1.top();return res;}
}s[MAX_N<<2];
/*namespace sgt
{#define mid ((l+r)>>1)#undef mid
}*/
void dfs1(int x,int fath)
{sz[x] = 1;fa[x] = fath;for(int i = p[x];i+1;i=e[i].next){int v = e[i].v;if(v==fath) continue;depth[v] = depth[x]+1;dfs1(v,x);sz[x]+=sz[v];if(sz[son[x]]<=sz[v]) son[x] = v;}
}
void dfs2(int u,int t)
{top[u] = t;id[u] = ++cnt;if(!son[u]) return;dfs2(son[u],t);for(int i = p[u];i+1;i=e[i].next){int v = e[i].v;if(v!=son[u]&&v!=fa[u])dfs2(v,v);}
}
struct node
{int l,r;bool operator <(const node other) const{return l < other.l;}
}B[MAX_N];
void update(int rt,int l,int r,int x,int y,int v,int flag)
{if(x<=l&&r<=y){if(flag==0) s[rt].push1(v);else s[rt].push2(v);return;}int mid = (l+r)>>1;if(x>mid) update(rt<<1|1,mid+1,r,x,y,v,flag);else if(y<=mid) update(rt<<1,l,mid,x,y,v,flag);else update(rt<<1,l,mid,x,y,v,flag),update(rt<<1|1,mid+1,r,x,y,v,flag);
}
void updates(int x,int y,int c,int flag)
{int f1 = top[x],f2 = top[y],scnt = 0;while(f1!=f2){if(depth[f1]<depth[f2])swap(x,y),swap(f1,f2);B[++scnt].r = id[x],B[scnt].l = id[f1];x = fa[f1];f1 = top[x];}if(depth[x]<depth[y])swap(x,y);B[++scnt].r = id[x],B[scnt].l = id[y];int last = 0;sort(B+1,B+1+scnt);for(int i = 1;i<=scnt;++i){if(B[i].l-1>=last+1) update(1,1,n,last+1,B[i].l-1,c,flag);last = B[i].r;}if(n>=last+1) update(1,1,n,last+1,n,c,flag);
}
void query(int rt,int l,int r,int x)
{ans = max(ans,s[rt].top());if(l==r) return ;int mid = (l+r)>>1;if(x<=mid) query(rt<<1,l,mid,x);else query(rt<<1|1,mid+1,r,x);
}
/*int root[MAX_N],cnt,sz;
namespace hjt
{#define mid ((l+r)>>1)struct node{int l,r,maxx;}T[MAX_N*40];#undef mid
}*/
struct Query{int x,y,v;
}Q[MAX_M];int main()
{//ios::sync_with_stdio(false);//freopen("a.txt","r",stdin);//freopen("b.txt","w",stdout);int m,a,b,ljq,x,y,v;init();n = read();m = read();for(int i = 1;i<n;++i){a=read();b=read();add(a,b);add(b,a);}depth[1] = 1;dfs1(1,0);cnt = 0;dfs2(1,1);for(int i = 1;i<=m;++i){ljq = read();if(ljq==0){x = read();y =read();v=read();Q[i].x = x;Q[i].y = y;Q[i].v = v;updates(x,y,v,0);}else if(ljq==1){v = read();updates(Q[v].x,Q[v].y,Q[v].v,1);}else{v = read();ans = -1;query(1,1,n,id[v]);printf("%d\n",ans);}}//fclose(stdin);//fclose(stdout);//cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;return 0;
}

P3833
树链剖分乱搞

/*if you can't see the repayWhy not just work step by steprubbish is relaxedto ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
//#pragma comment(linker, "/STACK:10240000,10240000")
using namespace std;#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))typedef pair<int,int> pll;
typedef long long ll;
typedef unsigned long long ull;
const ull hash1 = 201326611;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod =  (int)1e9+7;ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
//ull ha[MAX_N],pp[MAX_N];inline int read()
{int date = 0,m = 1; char ch = 0;while(ch!='-'&&(ch<'0'|ch>'9'))ch = getchar();if(ch=='-'){m = -1; ch = getchar();}while(ch>='0' && ch<='9'){date = date*10+ch-'0';ch = getchar();}return date*m;
}/*namespace sgt
{#define mid ((l+r)>>1)#undef mid
}*//*int root[MAX_N],cnt,sz;
namespace hjt
{#define mid ((l+r)>>1)struct node{int l,r,maxx;}T[MAX_N*40];#undef mid
}*/
const int MAX_N = 100025;
ll s[MAX_N<<2],col[MAX_N<<2];
int n,p[MAX_N],cnt,eid,id[MAX_N],son[MAX_N],depth[MAX_N],sz[MAX_N],fa[MAX_N],Rank[MAX_N],top[MAX_N];
void init()
{memset(p,-1,sizeof(p));eid = 0;
}
struct edge
{int v,next;
}e[MAX_N<<1];
void add(int u,int v)
{e[eid].v=  v;e[eid].next = p[u];p[u] = eid++;
}
void up(int rt)
{s[rt]  =s[rt<<1]+s[rt<<1|1];
}
void build(int rt,int l,int r)
{s[rt]  = col[rt] = 0;if(l==r){return;}int mid = (l+r)>>1;build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);up(rt);
}
void down(int rt,int l,int r)
{if(col[rt]){int mid = (l+r)>>1;col[rt<<1]+=col[rt];col[rt<<1|1]+=col[rt];s[rt<<1]+=1ll*(mid-l+1)*col[rt];s[rt<<1|1] += 1ll*(r-mid)*col[rt];col[rt] = 0;}
}
void update(int rt,int l,int r,int x,int y,int v)
{if(x<=l&&r<=y){col[rt]+=v;s[rt]+=1ll*(r-l+1)*v;return;}down(rt,l,r);int mid = (l+r)>>1;if(x>mid) update(rt<<1|1,mid+1,r,x,y,v);else if(y<=mid) update(rt<<1,l,mid,x,y,v);else update(rt<<1,l,mid,x,y,v),update(rt<<1|1,mid+1,r,x,y,v);up(rt);
}
ll query(int rt,int l,int r,int x,int y)
{if(x<=l&&r<=y){return s[rt];}down(rt,l,r);int mid = (l+r)>>1;if(x>mid) return query(rt<<1|1,mid+1,r,x,y);else if(y<=mid) return query(rt<<1,l,mid,x,y);else return (query(rt<<1,l,mid,x,y)+query(rt<<1|1,mid+1,r,x,y));
}
void dfs1(int x,int fath)
{depth[x] = depth[fath]+1;fa[x] = fath;sz[x] = 1;for(int i = p[x];i+1;i=e[i].next){int v = e[i].v;if(v==fath) continue;dfs1(v,x);sz[x]+=sz[v];if(sz[son[x]]<sz[v]) son[x] = v;}
}
void dfs2(int u,int t)
{top[u] = t;id[u] = ++cnt;Rank[cnt] = u;if(!son[u]) return;dfs2(son[u],t);for(int i = p[u];i+1;i=e[i].next){int v = e[i].v;if(v!=son[u]&&v!=fa[u])dfs2(v,v);}
}
void updates(int x,int y,int c)
{while(top[x]!=top[y]){if(depth[top[x]]<depth[top[y]])swap(x,y);update(1,1,n,id[top[x]],id[x],c);x = fa[top[x]];}if(id[x]>id[y]) swap(x,y);update(1,1,n,id[x],id[y],c);
}
int main()
{//ios::sync_with_stdio(false);//freopen("a.txt","r",stdin);//freopen("b.txt","w",stdout);int m,a,b,v;char opt[5];n = read();init();for(int i = 1;i<n;++i){a = read();b=read();a++,b++;add(a,b);add(b,a);}dfs1(1,0);dfs2(1,1);build(1,1,n);m = read();for(int i = 1;i<=m;++i){scanf("%s",opt);if(opt[0]=='A'){a = read();b=read();v=read();a++;b++;updates(a,b,v);}else{a = read();a++;printf("%lld\n",query(1,1,n,id[a],id[a]+sz[a]-1));}}//fclose(stdin);//fclose(stdout);//cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;return 0;
}

BZOJ4196
你只要发现 安装都是从这个点到1
删除都是这个点的儿子那么你就很容易搞了

/*if you can't see the repayWhy not just work step by steprubbish is relaxedto ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
//#pragma comment(linker, "/STACK:10240000,10240000")
using namespace std;#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))typedef pair<int,int> pll;
typedef long long ll;
typedef unsigned long long ull;
const ull hash1 = 201326611;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod =  (int)1e9+7;ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
//ull ha[MAX_N],pp[MAX_N];inline int read()
{int date = 0,m = 1; char ch = 0;while(ch!='-'&&(ch<'0'|ch>'9'))ch = getchar();if(ch=='-'){m = -1; ch = getchar();}while(ch>='0' && ch<='9'){date = date*10+ch-'0';ch = getchar();}return date*m;
}
const int MAX_N = 100025;
int n,eid,p[MAX_N],cnt,id[MAX_N],s[MAX_N<<2],col[MAX_N<<2],sz[MAX_N],depth[MAX_N],fa[MAX_N],top[MAX_N],son[MAX_N];
void init()
{memset(p,-1,sizeof(p));eid = 0;
}
struct edge
{int v,next;
}e[MAX_N<<1];
void add(int u,int v)
{e[eid].v = v;e[eid].next = p[u];p[u] = eid++;
}
void up(int rt)
{s[rt] = s[rt<<1]+s[rt<<1|1];
}
void down(int rt,int l,int r)
{if(col[rt]!=-1){int mid = (l+r)>>1;s[rt<<1] = (mid-l+1)*col[rt];s[rt<<1|1] = (r-mid)*col[rt];col[rt<<1] = col[rt<<1|1] = col[rt];col[rt] = -1;}
}
void build(int rt,int l,int r)
{col[rt] = -1;if(l==r) {s[rt] = 1;return;}int mid = (l+r)>>1;build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);up(rt);
}
void update(int rt,int l,int r,int x,int y,int v)
{if(x<=l&&r<=y){col[rt] = v;s[rt] = (r-l+1)*v;return;}down(rt,l,r);int mid = (l+r)>>1;if(x>mid) update(rt<<1|1,mid+1,r,x,y,v);else if(y<=mid) update(rt<<1,l,mid,x,y,v);else update(rt<<1,l,mid,x,y,v),update(rt<<1|1,mid+1,r,x,y,v);up(rt);
}
int query(int rt,int l,int r,int x,int y)
{if(x<=l&&r<=y){return s[rt];}down(rt,l,r);int mid = (l+r)>>1;if(x>mid) return query(rt<<1|1,mid+1,r,x,y);else if(y<=mid) return query(rt<<1,l,mid,x,y);else return (query(rt<<1,l,mid,x,y)+query(rt<<1|1,mid+1,r,x,y));
}
void dfs1(int x,int fath)
{sz[x] = 1;depth[x] = depth[fath]+1;fa[x] = fath;for(int i = p[x];i+1;i=e[i].next){int v = e[i].v;if(v==fath) continue;dfs1(v,x);sz[x]+=sz[v];if(sz[son[x]]<sz[v]) son[x] = v;}
}
void dfs2(int u,int t)
{top[u] = t;id[u] = ++cnt;if(!son[u]) return;dfs2(son[u],t);for(int i = p[u];i+1;i=e[i].next){int v = e[i].v;if(v!=son[u]&&v!=fa[u]) dfs2(v,v);}
}
int sum(int x,int y)
{int ans = 0;while(top[x]!=top[y]){if(depth[top[x]]<depth[top[y]]) swap(x,y);ans+=query(1,1,n,id[top[x]],id[x]);x = fa[top[x]];}if(id[x]>id[y]) swap(x,y);ans+=query(1,1,n,id[x],id[y]);return ans;
}
void updates(int x,int y,int c)
{while(top[x]!=top[y]){if(depth[top[x]] < depth[top[y]]) swap(x,y);update(1,1,n,id[top[x]],id[x],c);x = fa[top[x]];}if(id[x]>id[y]) swap(x,y);update(1,1,n,id[x],id[y],c);
}
/*namespace sgt
{#define mid ((l+r)>>1)#undef mid
}*//*int root[MAX_N],cnt,sz;
namespace hjt
{#define mid ((l+r)>>1)struct node{int l,r,maxx;}T[MAX_N*40];#undef mid
}*/int main()
{//ios::sync_with_stdio(false);//freopen("a.txt","r",stdin);//freopen("b.txt","w",stdout);int m,a,x;char opt[20];n = read();init();for(int i = 2;i<=n;++i){a = read();a++;add(a,i);add(i,a);}dfs1(1,0);dfs2(1,1);build(1,1,n);m = read();for(int i = 1;i<=m;++i){scanf("%s%d",opt,&x);x++;if(opt[0]=='i'){printf("%d\n",sum(1,x));updates(1,x,0);}else{printf("%d\n",sz[x]- query(1,1,n,id[x],id[x]+sz[x]-1));update(1,1,n,id[x],id[x]+sz[x]-1,1);}}//fclose(stdin);//fclose(stdout);//cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;return 0;
}

P3398
思路也很简单 你区间赋个值 再查一下就行了
以前不会树链剖分这种题估计都要哭爹喊娘了

/*if you can't see the repayWhy not just work step by steprubbish is relaxedto ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
//#pragma comment(linker, "/STACK:10240000,10240000")
using namespace std;#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))typedef pair<int,int> pll;
typedef long long ll;
typedef unsigned long long ull;
const ull hash1 = 201326611;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod =  (int)1e9+7;ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
//ull ha[MAX_N],pp[MAX_N];inline int read()
{int date = 0,m = 1; char ch = 0;while(ch!='-'&&(ch<'0'|ch>'9'))ch = getchar();if(ch=='-'){m = -1; ch = getchar();}while(ch>='0' && ch<='9'){date = date*10+ch-'0';ch = getchar();}return date*m;
}
const int MAX_N = 100025;
int Max(int a,int b){return a >b?a:b;}
int n,p[MAX_N],eid,cnt,id[MAX_N],sz[MAX_N],son[MAX_N],fa[MAX_N],maxx[MAX_N<<2],col[MAX_N<<2],top[MAX_N],depth[MAX_N];
void init()
{memset(p,-1,sizeof(p));eid = 0;
}
struct edge
{int v,next;
}e[MAX_N<<1];
void add(int u,int v)
{e[eid].v = v;e[eid].next = p[u];p[u] = eid++;
}
void up(int rt)
{maxx[rt] = Max(maxx[rt<<1],maxx[rt<<1|1]);
}
void build(int rt,int l,int r)
{maxx[rt] = 0;col[rt] = -1;if(l==r) return;int mid = (l+r)>>1;build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);
}
void down(int rt,int l,int r)
{if(col[rt]!=-1){maxx[rt<<1] = maxx[rt<<1|1] = col[rt];col[rt<<1] = col[rt<<1|1] = col[rt];col[rt] = -1;}
}
void update(int rt,int l,int r,int x,int y,int v)
{if(x<=l&&r<=y){maxx[rt] = v;col[rt] = v;return ;}down(rt,l,r);int mid = (l+r)>>1;if(x>mid) update(rt<<1|1,mid+1,r,x,y,v);else if(y<=mid) update(rt<<1,l,mid,x,y,v);else update(rt<<1,l,mid,x,y,v),update(rt<<1|1,mid+1,r,x,y,v);up(rt);
}
int query(int rt,int l,int r,int x,int y)
{if(x<=l&&r<=y){return maxx[rt];}down(rt,l,r);int mid = (l+r)>>1;if(x>mid) return query(rt<<1|1,mid+1,r,x,y);else if(y<=mid) return query(rt<<1,l,mid,x,y);else return Max(query(rt<<1,l,mid,x,y),query(rt<<1|1,mid+1,r,x,y));
}
void dfs1(int x,int fath)
{depth[x] = depth[fath]+1;fa[x] = fath;sz[x] = 1;for(int i = p[x];i+1;i=e[i].next){int v = e[i].v;if(v==fath) continue;dfs1(v,x);sz[x]+=sz[v];if(sz[son[x]]<sz[v]) son[x] = v;}
}
void dfs2(int u,int t)
{top[u] = t;id[u] = ++cnt;if(!son[u]) return;dfs2(son[u],t);for(int i = p[u];i+1;i=e[i].next){int v = e[i].v;if(v!=fa[u]&&v!=son[u]) dfs2(v,v);}
}
int sum(int x,int y)
{int ans = 0;while(top[x]!=top[y]){if(depth[top[x]]<depth[top[y]]) swap(x,y);ans = Max(ans,query(1,1,n,id[top[x]],id[x]));x=fa[top[x]];}if(id[x]>id[y]) swap(x,y);ans = Max(ans,query(1,1,n,id[x],id[y]));return ans;
}
void updates(int x,int y,int c)
{while(top[x]!=top[y]){if(depth[top[x]]<depth[top[y]]) swap(x,y);update(1,1,n,id[top[x]],id[x],c);x = fa[top[x]];}if(id[x]>id[y]) swap(x,y);update(1,1,n,id[x],id[y],c);
}
/*namespace sgt
{#define mid ((l+r)>>1)#undef mid
}*//*int root[MAX_N],cnt,sz;
namespace hjt
{#define mid ((l+r)>>1)struct node{int l,r,maxx;}T[MAX_N*40];#undef mid
}*/int main()
{//ios::sync_with_stdio(false);//freopen("a.txt","r",stdin);//freopen("b.txt","w",stdout);int m,a,b,x,y;n = read();m = read();init();for(int i = 1;i<n;++i){a = read();b=read();add(a,b);add(b,a);}build(1,1,n);dfs1(1,0);dfs2(1,1);for(int i = 1;i<=m;++i){a = read();b=read();x=read();y=read();updates(a,b,1);if(sum(x,y)==1) printf("Y\n");else printf("N\n");updates(a,b,0);}//fclose(stdin);//fclose(stdout);//cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;return 0;
}

BZOJ3531
这个题也是十分的骚呢 首先十分好想到对每个宗教都维护一颗线段树 大胆的建树 也就100000棵树吧糟糕 MLE了 那么就上动态开点啊 反正他最多有100000个人

/*if you can't see the repayWhy not just work step by steprubbish is relaxedto ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
//#pragma comment(linker, "/STACK:10240000,10240000")
using namespace std;#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))typedef pair<int,int> pll;
typedef long long ll;
typedef unsigned long long ull;
const ull hash1 = 201326611;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod =  (int)1e9+7;ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
//ull ha[MAX_N],pp[MAX_N];inline int read()
{int date = 0,m = 1; char ch = 0;while(ch!='-'&&(ch<'0'|ch>'9'))ch = getchar();if(ch=='-'){m = -1; ch = getchar();}while(ch>='0' && ch<='9'){date = date*10+ch-'0';ch = getchar();}return date*m;
}
int Max(int a,int b){return a>b?a:b;}
const int MAX_N = 100025;
const int N = 100000;
int p[MAX_N],now,eid,cnt,Rank[MAX_N],depth[MAX_N],top[MAX_N],id[MAX_N],belong[MAX_N],arr[MAX_N],sz[MAX_N],son[MAX_N],fa[MAX_N],root[MAX_N],maxx[MAX_N<<5],s[MAX_N<<5],lson[MAX_N<<5],rson[MAX_N<<5];
void init()
{eid = 0;memset(p,-1,sizeof(p));
}
struct edge
{int v,next;
}e[MAX_N<<1];
void add(int u,int v)
{e[eid].v = v;e[eid].next = p[u];p[u] = eid++;
}
void update(int &rt,int l,int r,int x,int v)
{if(!rt){rt = ++now;maxx[rt] = s[rt] = v;}if(l==r){maxx[rt] = v;s[rt] = v;return;}int mid = (l+r)>>1;if(x<=mid) update(lson[rt],l,mid,x,v);else update(rson[rt],mid+1,r,x,v);maxx[rt] = Max(maxx[lson[rt]],maxx[rson[rt]]);s[rt] = s[lson[rt]]+s[rson[rt]];
}
int query(int rt,int l,int r,int x,int y)
{if(!rt) return 0;if(x<=l&&r<=y){return s[rt];}int mid =  (l+r)>>1;if(x>mid) return query(rson[rt],mid+1,r,x,y);else if(y<=mid) return query(lson[rt],l,mid,x,y);else return query(lson[rt],l,mid,x,y)+query(rson[rt],mid+1,r,x,y);
}
int Query(int rt,int l,int r,int x,int y)
{if(!rt) return 0;if(x<=l&&r<=y) return maxx[rt];int mid = (l+r)>>1;if(x>mid) return Query(rson[rt],mid+1,r,x,y);else if(y<=mid) return Query(lson[rt],l,mid,x,y);else return Max(Query(lson[rt],l,mid,x,y),Query(rson[rt],mid+1,r,x,y));
}
void dfs1(int x,int fath)
{fa[x] = fath;depth[x] = depth[fath]+1;sz[x] = 1;for(int i = p[x];i+1;i=e[i].next){int v = e[i].v;if(v==fath) continue;dfs1(v,x);sz[x]+=sz[v];if(sz[son[x]]<sz[v]) son[x] = v;}
}
void dfs2(int u,int t)
{top[u] = t;id[u] = ++cnt;Rank[cnt] = u;if(!son[u]) return;dfs2(son[u],t);for(int i = p[u];i+1;i=e[i].next){int v= e[i].v;if(v!=son[u]&&v!=fa[u]) dfs2(v,v);}
}
int Sum(int x,int y,int rt)
{int ans = 0;while(top[x]!=top[y]){if(depth[top[x]]<depth[top[y]]) swap(x,y);ans += query(rt,1,N,id[top[x]],id[x]);x = fa[top[x]];}if(id[x]>id[y]) swap(x,y);ans += query(rt,1,N,id[x],id[y]);return ans;
}
int sum(int x,int y,int rt)
{int ans = 0;while(top[x]!=top[y]){if(depth[top[x]]<depth[top[y]]) swap(x,y);ans = Max(ans,Query(rt,1,N,id[top[x]],id[x]));x = fa[top[x]];}if(id[x]>id[y]) swap(x,y);ans = Max(ans,Query(rt,1,N,id[x],id[y]));return ans;
}
/*namespace sgt
{#define mid ((l+r)>>1)#undef mid
}*//*int root[MAX_N],cnt,sz;
namespace hjt
{#define mid ((l+r)>>1)struct node{int l,r,maxx;}T[MAX_N*40];#undef mid
}*/int main()
{//ios::sync_with_stdio(false);//freopen("a.txt","r",stdin);//freopen("b.txt","w",stdout);int n,m,a,b,x,y;n = read();m = read();char opt[5];for(int i = 1;i<=n;++i){arr[i] = read();belong[i] = read();}init();for(int i = 1;i<n;++i){a = read();b= read();add(a,b);add(b,a);}dfs1(1,0);dfs2(1,1);for(int i = 1;i<=n;++i){update(root[belong[i]],1,N,id[i],arr[i]);}for(int i = 1;i<=m;++i){scanf("%s",opt);x = read();y =read();if(opt[0]=='Q'){if(opt[1]=='S'){printf("%d\n",Sum(x,y,root[belong[x]]));}else{printf("%d\n",sum(x,y,root[belong[x]]));}}else{if(opt[1]=='C'){int last = belong[x];update(root[last],1,N,id[x],0);belong[x] = y;update(root[y],1,N,id[x],arr[x]);}else{arr[x] = y;update(root[belong[x]],1,N,id[x],y);}}}//fclose(stdin);//fclose(stdout);//cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;return 0;
}

HDU6547
女生赛的题 写完队友问我有没有树链剖分板子 脸都没了 作为数据结构选手 西安E都不懂点和点之间的最短路是什么 队友这样问 小菜鸡决定好好学下树链剖分
这题能读题到码完提交AC仅用14分钟 希望今年区域赛小菜鸡也能这样

/*if you can't see the repayWhy not just work step by steprubbish is relaxedto ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
//#pragma comment(linker, "/STACK:10240000,10240000")
using namespace std;#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))typedef pair<int,int> pll;
typedef long long ll;
typedef unsigned long long ull;
const ull hash1 = 201326611;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod =  (int)1e9+7;ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
//ull ha[MAX_N],pp[MAX_N];inline int read()
{int date = 0,m = 1; char ch = 0;while(ch!='-'&&(ch<'0'|ch>'9'))ch = getchar();if(ch=='-'){m = -1; ch = getchar();}while(ch>='0' && ch<='9'){date = date*10+ch-'0';ch = getchar();}return date*m;
}
const int MAX_N = 100025;
int n,p[MAX_N],eid,arr[MAX_N],cnt,top[MAX_N],Rank[MAX_N],id[MAX_N],sz[MAX_N],son[MAX_N],fa[MAX_N],depth[MAX_N],maxx[MAX_N<<2];
ll s[MAX_N<<2];
void init()
{memset(p,-1,sizeof(p));eid = 0;
}
struct edge
{int v,next;
}e[MAX_N<<1];
void add(int u,int v)
{e[eid].v = v;e[eid].next = p[u];p[u] = eid++;
}
int Max(int a,int b) {return a > b?a:b;}
void up(int rt)
{s[rt] = s[rt<<1]+s[rt<<1|1];maxx[rt] = Max(maxx[rt<<1],maxx[rt<<1|1]);
}
void build(int rt,int l,int r)
{if(l==r){maxx[rt] = s[rt] = arr[Rank[l]];return ;}int mid =(l+r)>>1;build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);up(rt);
}
void update(int rt,int l,int r,int x,int y)
{if(maxx[rt]==1) return;if(l==r) {maxx[rt] = sqrt(maxx[rt]);s[rt] = maxx[rt];return;}int mid = (l+r)>>1;if(x>mid) update(rt<<1|1,mid+1,r,x,y);else if(y<=mid) update(rt<<1,l,mid,x,y);else update(rt<<1,l,mid,x,y),update(rt<<1|1,mid+1,r,x,y);up(rt);
}
ll query(int rt,int l,int r,int x,int y)
{if(x<=l&&r<=y) return s[rt];int mid  = (l+r)>>1;if(x>mid) return query(rt<<1|1,mid+1,r,x,y);else if(y<=mid) return query(rt<<1,l,mid,x,y);else return query(rt<<1,l,mid,x,y)+query(rt<<1|1,mid+1,r,x,y);
}
void dfs1(int x,int fath)
{fa[x] = fath;depth[x] = depth[fath]+1;sz[x] = 1;for(int i = p[x];i+1;i=e[i].next){int  v =e[i].v;if(v==fath) continue;dfs1(v,x);sz[x]+=sz[v];if(sz[son[x]]<sz[v]) son[x] = v;}
}
void dfs2(int u,int t)
{top[u] = t;id[u] = ++cnt;Rank[cnt ] = u;if(!son[u]) return;dfs2(son[u],t);for(int i = p[u];i+1;i=e[i].next){int v =e[i].v;if(v!=son[u]&&v!=fa[u]) dfs2(v,v);}
}
ll sum(int x,int y)
{ll ans = 0;while(top[x]!=top[y]){if(depth[top[x]]<depth[top[y]]) swap(x,y);ans += query(1,1,n,id[top[x]],id[x]);x = fa[top[x]];}if(id[x]>id[y]) swap(x,y);ans+=query(1,1,n,id[x],id[y]);return ans;
}
void updates(int x,int y)
{while(top[x]!=top[y]){if(depth[top[x]]<depth[top[y]]) swap(x,y);update(1,1,n,id[top[x]],id[x]);x = fa[top[x]];}if(id[x]>id[y]) swap(x,y);update(1,1,n,id[x],id[y]);
}
/*namespace sgt
{#define mid ((l+r)>>1)#undef mid
}*//*int root[MAX_N],cnt,sz;
namespace hjt
{#define mid ((l+r)>>1)struct node{int l,r,maxx;}T[MAX_N*40];#undef mid
}*/int main()
{//ios::sync_with_stdio(false);//freopen("a.txt","r",stdin);//freopen("b.txt","w",stdout);int a,b,m,opt,x,y;n  =read();m = read();init();for(int i = 1;i<=n;++i) arr[i] = read();for(int i = 1;i<n;++i){a = read();b = read();add(a,b);add(b,a);}dfs1(1,0);dfs2(1,1);build(1,1,n);for(int i = 1;i<=m;++i){opt = read();x=read();y=read();if(opt==0){updates(x,y);}else{printf("%lld\n",sum(x,y));}}//fclose(stdin);//fclose(stdout);//cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;return 0;
}

西安邀请赛E
这道题线段树版本有道升级版本
FZU2105
然后小菜鸡ljq很容易就想到线段树怎么做
然后跟队友说 这题能出
等下 他问点和点之间的最短路
woc 点和点之间的最短路是什么啊 猝

拆位 维护区间1的个数 奇数表示存在 偶数表示不存在

/*if you can't see the repayWhy not just work step by steprubbish is relaxedto ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
//#pragma comment(linker, "/STACK:10240000,10240000")
using namespace std;#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))typedef pair<int,int> pll;
typedef long long ll;
typedef unsigned long long ull;
const ull hash1 = 201326611;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod =  (int)1e9+7;ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
//ull ha[MAX_N],pp[MAX_N];inline int read()
{int date = 0,m = 1; char ch = 0;while(ch!='-'&&(ch<'0'|ch>'9'))ch = getchar();if(ch=='-'){m = -1; ch = getchar();}while(ch>='0' && ch<='9'){date = date*10+ch-'0';ch = getchar();}return date*m;
}
const int MAX_N = 100025;
int ans,n,p[MAX_N],eid,cnt,id[MAX_N],Rank[MAX_N],arr[MAX_N],sz[MAX_N],fa[MAX_N],son[MAX_N],s[MAX_N<<2][31],col[MAX_N<<2][31],depth[MAX_N],top[MAX_N];
void init()
{eid = 0;memset(p,-1,sizeof(p));
}
struct edge
{int v,next;
}e[MAX_N<<1];
void add(int u,int v)
{e[eid].v = v;e[eid].next = p[u];p[u] = eid++;
}
void up(int rt)
{for(int i = 0;i<30;++i){s[rt][i] = s[rt<<1][i] + s[rt<<1|1][i];}
}
void build(int rt,int l,int r)
{for(int i = 0;i<30;++i) col[rt][i] = -1;if(l==r){for(int i = 0;i<30;++i){if((1<<i)&arr[Rank[l]]) s[rt][i] = 1;else s[rt][i] = 0;}return ;}int mid = (l+r)>>1;build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);up(rt);
}
void down(int rt,int l,int r)
{int mid = (l+r)>>1;for(int i = 0;i<30;++i){if(col[rt][i]!=-1){col[rt<<1|1][i] = col[rt<<1][i] = col[rt][i];if(col[rt][i]==1){s[rt<<1][i] = mid-l+1;s[rt<<1|1][i] = r-mid;}else{s[rt<<1][i] = 0;s[rt<<1|1][i] = 0;}col[rt][i] = -1;}}
}
void update(int rt,int l,int r,int x,int y,int v,int flag)
{if(x<=l&&r<=y){if(flag==1){for(int i = 0;i<30;++i){if((1<<i)&v){col[rt][i] = 1;s[rt][i] = r-l+1;}}}else{for(int i = 0;i<30;++i){if(!((1<<i)&v)){col[rt][i] = 0;s[rt][i] = 0;}}}return;}down(rt,l,r);int mid = (l+r)>>1;if(x>mid) update(rt<<1|1,mid+1,r,x,y,v,flag);else if(y<=mid) update(rt<<1,l,mid,x,y,v,flag);else update(rt<<1,l,mid,x,y,v,flag),update(rt<<1|1,mid+1,r,x,y,v,flag);up(rt);
}
void query(int rt,int l,int r,int x,int y)
{if(x<=l&&r<=y){for(int i = 0;i<30;++i){if(s[rt][i]&1) ans^=(1<<i);}return;}down(rt,l,r);int mid = (l+r)>>1;if(x>mid)  query(rt<<1|1,mid+1,r,x,y);else if(y<=mid)  query(rt<<1,l,mid,x,y);else  query(rt<<1,l,mid,x,y),query(rt<<1|1,mid+1,r,x,y);
}
void dfs1(int x,int fath)
{fa[x] = fath;depth[x] = depth[fath]+1;sz[x] = 1;for(int i = p[x];i+1;i=e[i].next){int v = e[i].v;if(v==fath) continue;dfs1(v,x);sz[x]+=sz[v];if(sz[son[x]]<sz[v]) son[x] = v;}
}
void dfs2(int u,int t)
{top[u] = t;id[u] = ++cnt;Rank[cnt] = u;if(!son[u]) return;dfs2(son[u],t);for(int i = p[u];i+1;i=e[i].next){int v  =e[i].v;if(v!=son[u]&&v!=fa[u]) dfs2(v,v);}
}
void sum(int x,int y)
{while(top[x]!=top[y]){if(depth[top[x]]<depth[top[y]]) swap(x,y);query(1,1,n,id[top[x]],id[x]);x = fa[top[x]];}if(id[x]>id[y]) swap(x,y);query(1,1,n,id[x],id[y]);
}
void updates(int x,int y,int c,int flag)
{while(top[x]!=top[y]){if(depth[top[x]]<depth[top[y]]) swap(x,y);update(1,1,n,id[top[x]],id[x],c,flag);x = fa[top[x]];}if(id[x]>id[y]) swap(x,y);update(1,1,n,id[x],id[y],c,flag);
}
/*namespace sgt
{#define mid ((l+r)>>1)#undef mid
}*//*int root[MAX_N],cnt,sz;
namespace hjt
{#define mid ((l+r)>>1)struct node{int l,r,maxx;}T[MAX_N*40];#undef mid
}*/int main()
{//ios::sync_with_stdio(false);//freopen("a.txt","r",stdin);//freopen("b.txt","w",stdout);int m,x,y,opt;n = read();m = read();for(int i = 1;i<=n;++i) arr[i] = read();init();for(int i = 1;i<n;++i){x = read();y=read();add(x,y);add(y,x);}dfs1(1,0);dfs2(1,1);build(1,1,n);for(int i = 1;i<=n;++i){opt = read();x=read();y=read();if(opt==1){updates(1,x,y,1);}else if(opt==2){updates(1,x,y,2);}else{ans = 0;sum(1,x);if(ans!=y) printf("YES\n");else printf("NO\n");}}//fclose(stdin);//fclose(stdout);//cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;return 0;
}

小清的树链剖分10题日志01 树链剖分种果子 有你好果子吃的相关推荐

  1. 小清的线段树25题日志01 线段树下你和我 欢乐多又多

    前言 难度大致会按排序来 就不写总结啦 嘻嘻 适合刚学线段树的人(和我一样 练手 /*if you can't see the repayWhy not just work step by stepr ...

  2. 洛谷3384(树链剖分模板题)

    题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z 操作2: 格式 ...

  3. 洛谷P3384 - 树链剖分(树链剖分模板题)

    题目链接 https://www.luogu.org/problemnew/show/P3384 [描述] 树链剖分模板题,记一下板子 #include<bits/stdc++.h> #d ...

  4. 【树链剖分】「ZJOI2008」树的统计

    前置知识 树链剖分的思想及能解决的问题 树链剖分用于将树分割成若干条链的形式,以维护树上路径的信息. 具体来说,将整棵树剖分为若干条链,使它组合成线性结构,然后用其他的数据结构维护信息. 树链剖分(树 ...

  5. 树链剖分(bzoj 1036: [ZJOI2008]树的统计Count)

    树链剖分: 把一棵树剖分为若干条链,然后利用数据结构(树状数组,SBT,Splay,线段树等等)去维护每一条链,复杂度 为O(logn),总体复杂度O(nlog²n) 步骤: ①将树的边分成重边和轻边 ...

  6. 2021-08-30王道 数据结构 第5章 树与二叉树 p185 第10题

    第5章 树与二叉树 5.5 树与二叉树的运用 综合应用题 第10题 void Output(BSTANode *bt,keyType k) {if(bt==NULL)return;if(bt-> ...

  7. hdu1166敌兵布阵 树状数组裸题

    树状数组裸题 动态更新区间内的点,动态查询区间和 敌兵布阵 ac代码 #include<iostream> #include<algorithm> #include<cs ...

  8. 区块链基础知识系列 第三课 区块链中的默克尔树

    "区块链是实现无中心分布式总账的一种技术.除了采用块.链结构的典型区块链以外,还有其他的方式实现分布式总账这个需求.总账技术的基本单元是'交易',整个账本是由一条条的交易构成.'块'类似于账 ...

  9. 互联网晚报 | 9月28日 星期二 | 乐视手机宣布回归;小鹏汽车累计交付量突破10万台;苹果售出20亿部iPhone...

    ‍ 今日看点 ✦ 快手搜索发布首个品牌Slogan,日均搜索次数超3亿 ✦ 乐视宣布手机业务正式回归并发布新品S1,内置华为HMS服务 ✦ 合合信息提交科创板IPO招股书:拟募资14.9亿元,去年净利 ...

最新文章

  1. 刻意练习:LeetCode实战 -- Task24. 恢复二叉搜索树
  2. HTML如何让图片覆盖背景颜色,css – 使用rgba背景颜色覆盖背景图像
  3. 非线性方程组牛顿迭代法matlab,matlab实现牛顿迭代法求解非线性方程组
  4. cesium首次加载gltf模型成功
  5. 关于数据中台的深度思考与总结,20000 字不到一丢丢。。。
  6. Git使用教程:最详细、最傻瓜、最浅显、真正手把手教!(转载学习)
  7. 前端学习(3207):js中的事件绑定
  8. python-文件操作(1)
  9. html怎么快速收录,如何让网站快速收录?网站提高收录的10种方法
  10. 计算机基础ppt说课稿,计算机基础说课稿ppt课件
  11. android 获取手机的MAC地址
  12. webview的一些使用小窍门和需注意的地方
  13. rem 用户改变字体大小_用户可以更改字体大小
  14. 信捷 XDH Ethercat 正负极限的设置
  15. [Tool] 仿博客园插入代码的 WLW 插件
  16. mysql 中文数字转换_数据库中数字和中文的转换问题
  17. 为什么我带的00后后辈在职场平步青云,比我还先升职了该走还是留?
  18. 花匠(最长波浪子序列——DP + 权值线段树)
  19. 采用16线激光雷达调用cartographer室内建图
  20. 如何通过外网环境访问本地的Web项目

热门文章

  1. 钱继志 计算机教程,photoshop
  2. ubuntu系统的快捷键,软件等配置
  3. c语言新手游戏,游戏c语言代码 - 新手交流 - 中国红客联盟 - Powered by HUC
  4. 安装Phalcon框架
  5. html中gif图怎么写,请问如何写html格式的邮件 带gif和图片的
  6. 【架构师修炼之路】Redis 极简教程 : 基本数据结构, 跳表原理, Spring Boot 项目使用实例
  7. 初中数学老师计算机培训反思,初中数学教师培训研修总结范文(精选5篇)
  8. 怎么把固定的电脑IP 改为自动获取
  9. # 什么 是SCI SSCI CSSCI ?
  10. flink-table-planner-blink