您的位置:首页 > 其它

树链剖分专题

2015-06-17 22:06 363 查看
学习了一下树链剖分,找了几个有意义的题目训练一下

前4题是基础训练, A、B是AOV树(点记录信息) C、D是AOE树(边记录信息)

*注意一下poj好像是提交的代码包含/**/这样的注释会出问题

A、HDU 3966

题意:给你N个点M条边的一棵AOV树,有P次操作

操作分别是:‘I’:将C1到C2路径上的点增加K;

     ‘D’:将C1到C2路径上的点减少K;

     ‘Q’:问你C点上的权;

解:树链剖分基础题,需要注意的是杭电的服务器是windows的,代码中加入用下面这句话扩栈

#pragma comment(linker, "/STACK:1024000000,1024000000")


/*
* Problem:
* Author:  SHJWUDP
* Created Time:  2015/6/11 星期四 15:57:34
* File Name: 233.cpp
* State:
* Memo:
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int INF=0x7f7f7f7f;

const int MaxA=1e4+7;

struct Edge {
int v, nt;
int w;
Edge() {}
Edge(int v, int nt, int w):v(v), nt(nt), w(w){}
} edges[MaxA<<1];

int head[MaxA], edgeNum;

struct SegmentTree {
int n;
struct Node {
int mx, mi;
int mark;
} c[MaxA<<2];
int *val;
int p, v;
int L, R;
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
#define RUSH Node& u=c[rt]; Node& ls=c[rt<<1]; Node& rs=c[rt<<1|1];

void pushUp(int rt) {
RUSH
u.mx=max(ls.mx, rs.mx);
u.mi=min(ls.mi, rs.mi);
}

void pushDown(int rt) {
RUSH
if(u.mark) {
ls.mx=-ls.mx; ls.mi=-ls.mi; swap(ls.mx, ls.mi);
ls.mark^=1;
rs.mx=-rs.mx; rs.mi=-rs.mi; swap(rs.mx, rs.mi);
rs.mark^=1;
u.mark=0;
}
}

void doBuild(int l, int r, int rt) {
c[rt].mark=0;
if(l==r) {
c[rt].mx=c[rt].mi=val[l];
} else {
int m=(l+r)>>1;
doBuild(lson);
doBuild(rson);
pushUp(rt);
}
}

void build(int n, int *val) {
this->n=n; this->val=val;
doBuild(1, n, 1);
}

void doChange(int l, int r, int rt) {
if(l==r) {
c[rt].mx=c[rt].mi=v;
} else {
pushDown(rt);
int m=(l+r)>>1;
if(p<=m) doChange(lson);
else doChange(rson);
pushUp(rt);
}
}

void change(int p, int v) {
this->p=p; this->v=v;
doChange(1, n, 1);
}

void doNegate(int l, int r, int rt) {
if(L<=l && r<=R) {
c[rt].mx=-c[rt].mx; c[rt].mi=-c[rt].mi;
swap(c[rt].mx, c[rt].mi);
c[rt].mark^=1;
} else {
pushDown(rt);
int m=(l+r)>>1;
if(L<=m) doNegate(lson);
if(m<R) doNegate(rson);
pushUp(rt);
}
}

void negate(int L, int R) {
this->L=L; this->R=R;
doNegate(1, n, 1);
}

int doQuery(int l, int r, int rt) {
if(L<=l && r<=R) {
return c[rt].mx;
} else {
pushDown(rt);
int m=(l+r)>>1;
int res=-INF;
if(L<=m) res=max(res, doQuery(lson));
if(m<R) res=max(res, doQuery(rson));
return res;
}
}

int query(int L, int R) {
this->L=L; this->R=R;
return doQuery(1, n, 1);
}
#undef lson
#undef rson
#undef RUSH
} st;

int N;
int oval[MaxA], val[MaxA];
void init() {
edgeNum=0;
memset(head, -1, sizeof(head));
}
void addEdge(int u, int v, int w) {
edges[edgeNum]=Edge(v, head[u], w);
head[u]=edgeNum++;
}
namespace LCT {
int fa[MaxA];
int siz[MaxA];
int son[MaxA];
int dep[MaxA];
int top[MaxA];
int w[MaxA];
int id;
int e2p[MaxA];        ///边到点的映射

int dfs1(int u, int d) {
siz[u]=1; dep[u]=d; son[u]=-1;
for(int i=head[u]; ~i; i=edges[i].nt) {
Edge& e=edges[i];
if(e.v==fa[u]) continue;
e2p[(i>>1)+1]=e.v;        ///边到点的映射
fa[e.v]=u; oval[e.v]=e.w;    ///以点代边
siz[u]+=dfs1(e.v, d+1);
if(son[u]==-1 || siz[son[u]]<siz[e.v]) son[u]=e.v;
}
return siz[u];
}

void dfs2(int u, int tp) {
w[u]=++id; top[u]=tp;
if(~son[u]) dfs2(son[u], tp);
for(int i=head[u]; ~i; i=edges[i].nt) {
Edge& e=edges[i];
if(e.v==fa[u] || e.v==son[u]) continue;
dfs2(e.v, e.v);
}
}

void init() {
int root=1;
id=0; oval[root]=-INF; ///以点代边,根结点不代表任何边
fa[root]=-1;
dfs1(root, 0);
dfs2(root, root);
for(int i=1; i<=N; i++) {
val[w[i]]=oval[i];
}
st.build(N, val);
}

void change(int p, int v) {
st.change(w[e2p[p]], v);
}

int find(int u, int v, int op) {
int res=-INF;
int f1=top[u], f2=top[v];
while(f1!=f2) {
if(dep[f1]<dep[f2]) { swap(f1, f2); swap(u, v); }
if(op==0) res=max(res, st.query(w[f1], w[u]));
else st.negate(w[f1], w[u]);
u=fa[f1]; f1=top[u];
}
if(u==v) return res;
if(dep[u]>dep[v]) swap(u, v);
if(op==0) res=max(res, st.query(w[u]+1, w[v]));
else st.negate(w[u]+1, w[v]);
return res;
}
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in", "r", stdin);
//freopen("out", "w", stdout);
#endif
int T;
scanf("%d", &T);
while(T--) {
scanf("%d", &N);
init();
for(int i=1; i<N; i++) {
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
addEdge(a, b, c);
addEdge(b, a, c);
}

LCT::init();
char op[7];
while(scanf("%s", op), op[0]!='D') {
int a, b;
scanf("%d%d", &a, &b);
switch(op[0]) {
case 'C': LCT::change(a, b);
break;
case 'N': LCT::find(a, b, 1);
break;
default: printf("%d\n", LCT::find(a, b, 0));
}
}
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: