本文主要是介绍BZOJ 3531 旅行【树链剖分】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
[Sdoi2014]
简单的树链剖分
以每个信仰应该建一个线段树,空间复杂度为 O(5×1010)
因此会爆空间,所以需要动态申请空间。
// whn6325689
// Mr.Phoebe
// http://blog.csdn.net/u013007900
#include <algorithm>
#include <iostream>
#include <iomanip>
#include <cstring>
#include <climits>
#include <complex>
#include <fstream>
#include <cassert>
#include <cstdio>
#include <bitset>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <ctime>
#include <set>
#include <map>
#include <cmath>
#include <functional>
#include <numeric>
#pragma comment(linker, "/STACK:1024000000,1024000000")using namespace std;#define eps 1e-9
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
#define LLINF 1LL<<62
#define speed std::ios::sync_with_stdio(false);typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<ll, ll> pll;
typedef complex<ld> point;
typedef pair<int, int> pii;
typedef pair<pii, int> piii;
typedef vector<int> vi;#define CLR(x,y) memset(x,y,sizeof(x))
#define CPY(x,y) memcpy(x,y,sizeof(x))
#define clr(a,x,sz) memset(a,x,sizeof(a[0])*(sz))
#define cpy(a,x,sz) memcpy(a,x,sizeof(a[0])*(sz))
#define debug(a) cout << #a" = " << (a) << endl;
#define debugarry(a, n) for (int i = 0; i < (n); i++) { cout << #a"[" << i << "] = " << (a)[i] << endl; }#define mp(x,y) make_pair(x,y)
#define pb(x) push_back(x)
#define lowbit(x) (x&(-x))#define MID(x,y) (x+((y-x)>>1))
#define getidx(l,r) (l+r | l!=r)
#define ls getidx(l,mid)
#define rs getidx(mid+1,r)
#define lson l,mid
#define rson mid+1,rtemplate<class T>
inline bool read(T &n)
{T x = 0, tmp = 1;char c = getchar();while((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar();if(c == EOF) return false;if(c == '-') c = getchar(), tmp = -1;while(c >= '0' && c <= '9') x *= 10, x += (c - '0'),c = getchar();n = x*tmp;return true;
}
template <class T>
inline void write(T n)
{if(n < 0){putchar('-');n = -n;}int len = 0,data[20];while(n){data[len++] = n%10;n /= 10;}if(!len) data[len++] = 0;while(len--) putchar(data[len]+48);
}
//-----------------------------------const int MAXN=100010;struct SegTree *nil;struct SegTree
{SegTree *son[2];int maxn,sum;SegTree(){maxn=sum=0;son[0]=son[1]=nil;}void update(int l,int r,int x,int c){if(l==r){maxn=sum=c;return;}int mid=MID(l,r);if(x<=mid){if(son[0]==nil)son[0]=new SegTree();son[0]->update(lson,x,c);}else{if(son[1]==nil)son[1]=new SegTree();son[1]->update(rson,x,c);}maxn=max(son[0]->maxn,son[1]->maxn);sum=son[0]->sum+son[1]->sum;}int GetSum(int l,int r,int x,int y){if(this==nil) return 0;if(l==x && y==r) return sum;int mid=MID(l,r);if(y <= mid) return son[0]->GetSum(lson,x,y);if(x > mid) return son[1]->GetSum(rson,x,y);int left=son[0]->GetSum(lson,x,mid);int right=son[1]->GetSum(rson,mid+1,y);return left + right;}int GetMax(int l,int r,int x,int y){if(this==nil) return 0;if(l==x && y==r) return maxn;int mid=MID(l,r);if(y <= mid) return son[0]->GetMax(lson,x,y);if(x > mid) return son[1]->GetMax(rson,x,y);int left=son[0]->GetMax(lson,x,mid);int right=son[1]->GetMax(rson,mid+1,y);return max(left,right);}
} none,*root[MAXN];int n,m;
struct Edge
{int to,next;
} e[MAXN<<1];
int head[MAXN],tot;void init()
{CLR(head,-1);tot=0;nil=&none;
}inline void addedge(int x,int y)
{e[tot].next=head[x];e[tot].to=y;head[x]=tot++;
}int p[MAXN],belief[MAXN];
char str[22];
int sz[MAXN],son[MAXN],fa[MAXN],dep[MAXN];
int top[MAXN],dfn[MAXN],cnt;void dfs(int x,int last)
{dep[x]=dep[last]+1;fa[x]=last;son[x]=-1;sz[x]=1;int max_sz=0;for(int i=head[x]; ~i; i=e[i].next){if(e[i].to==last) continue;dfs(e[i].to,x);sz[x]+=sz[e[i].to];if(sz[e[i].to]>max_sz)max_sz=sz[e[i].to],son[x]=e[i].to;}
}void getid(int x,int _top)
{dfn[x]=++cnt;top[x]=_top;if(~son[x]) getid(son[x],_top);for(int i=head[x]; ~i; i=e[i].next){if(e[i].to==fa[x] || e[i].to==son[x]) continue;getid(e[i].to,e[i].to);}
}inline int GetSum(int x,int y,int p)
{int re=0;while(top[x]!=top[y]){if(dep[top[x]] < dep[top[y]]) swap(x,y);re+=root[p]->GetSum(1,n,dfn[top[x]],dfn[x]);x=fa[top[x]];}if(dep[x]<dep[y]) swap(x,y);re += root[p]->GetSum(1,n,dfn[y],dfn[x]);return re;
}inline int GetMax(int x,int y,int p)
{int re=0;while(top[x] != top[y]){if(dep[top[x]] < dep[top[y]]) swap(x,y);re=max(re,root[p]->GetMax(1,n,dfn[top[x]],dfn[x]));x=fa[top[x]];}if(dep[x]<dep[y]) swap(x,y);re=max(re,root[p]->GetMax(1,n,dfn[y],dfn[x]));return re;
}int main()
{init();scanf("%d %d",&n,&m);for(int i=0; i<MAXN; i++)root[i]=new SegTree();for(int i=1; i<=n; i++)scanf("%d %d",&p[i],&belief[i]);for(int x,y,i=1; i<n; i++){scanf("%d %d",&x,&y);addedge(x,y),addedge(y,x);}dfs(1,0);getid(1,1);for(int i=1; i<=n; i++)root[belief[i]]->update(1,n,dfn[i],p[i]);for(int x,y,i=1; i<=m; i++){scanf("%s%d%d",str,&x,&y);if(str[0]=='C' && str[1]=='C'){root[belief[x]]->update(1,n,dfn[x],0);root[belief[x]=y]->update(1,n,dfn[x],p[x]);}else if(str[0]=='C' && str[1]=='W')root[belief[x]]->update(1,n,dfn[x],p[x]=y);else if(str[0]=='Q' && str[1]=='S')printf("%d\n",GetSum(x,y,belief[x]));elseprintf("%d\n",GetMax(x,y,belief[x]));}return 0;
}
这篇关于BZOJ 3531 旅行【树链剖分】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!