您的位置:首页 > 其它

BZOJ 3531 旅行【树链剖分】

2015-10-02 15:42 288 查看
[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,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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: