BZOJ 3531 旅行【树链剖分】
2015-10-02 15:42
288 查看
[Sdoi2014]
简单的树链剖分
以每个信仰应该建一个线段树,空间复杂度为O(5×1010)
因此会爆空间,所以需要动态申请空间。
简单的树链剖分
以每个信仰应该建一个线段树,空间复杂度为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,r template<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])); else printf("%d\n",GetMax(x,y,belief[x])); } return 0; }
相关文章推荐
- 数据库最最常用语句(10年工作笔记)
- java抽象类
- 如何在Linux上使用netstat命令查证DDOS攻击
- android布局属性大全
- 安卓控件使用系列12:CheckBox复选框控件的使用
- 轮廓线动态规划问题
- swift闭包
- iOS 多线程实例(NSThread售票窗口的模拟)
- web前端性能优化
- ZOJ - 2421 Recaman's Sequence(打表水题)
- swift函数
- C++单例模式
- yael for ubuntu 部署日志
- HDU 3639 Hawk-and-Chicken
- happens-before规则解析
- 在Windows下制作静态库和动态库
- HDU 1269 迷宫城堡(强连通)
- Rich控件一
- 值参数
- ForTran快速入门