休息了两天,今天开始做树链剖分,除了模板长以外,还是挺好理解的。就只是线段树+剖分独特的函数,然后树链剖分所用的数组有点多,没了。其中需要注意的一个点是“链”(路径)不一定是从根节点到叶子节点的,轻儿子这个点它也有重儿子啊啊啊。
再说这个题,单点更新,区间取相反数,区间求最大值。
/***********
poj3237
2015.1.23
2504K 657MS C++ 6396B
***********/
#include
#include
#include
#include
using namespace std;
const int maxn=101010+5;
const int maxm=maxn+maxn;
struct EDGENODE
{
int to,w,next;
}edges[maxm];
int head[maxn],edge;
inline void init(){
edge=0;
memset(head,-1,sizeof(head));
}
inline void addedge(int u,int v,int w)
{
edges[edge].w=w,edges[edge].to=v,edges[edge].next=head[u],head[u]=edge++;
edges[edge].w=w,edges[edge].to=u,edges[edge].next=head[v],head[v]=edge++;
}
int que[maxn],son[maxn],idx[maxn],dep[maxn],siz[maxn],belong[maxn],fa[maxn],top[maxn],len[maxn],sump[maxn],seg[maxn],wei[maxn];
int l,r,ans,cnt,n;
bool vis[maxn];
char cmd[22];
void split()
{
memset(dep,-1,sizeof(dep));
l=0;
dep[que[r=1]=1]=0;
fa[1]=-1;
wei[1]=0;
while(l0;i--)
{
int u=que[i],p=-1;
siz[u]=1;
son[u]=p;
for(int k=head[u];k!=-1;k=edges[k].next)
{
int v=edges[k].to;
if(vis[v])
{
siz[u]+=siz[v];
if(p==-1||siz[v]>siz[p])
{
son[u]=v;
p=v;
}
}
}
if(p==-1)
{
idx[u]=len[++cnt]=1;
belong[top[cnt]=u]=cnt;
}
else
{
idx[u]=++len[belong[u]=belong[p]];
top[belong[u]]=u;
}
vis[u]=true;
}
}
const int INF=0x3f3f3f3f;
struct SegmentTree
{
int num[maxn];
struct Tree
{
int l,r,max,min;
bool neg;
};
Tree tree[maxn*4];
void push_down(int root)
{
if(tree[root].neg)
{
if(tree[root].l!=tree[root].r)
{
tree[root<<1].neg^=1;
tree[root<<1|1].neg^=1;
swap(tree[root<<1].max,tree[root<<1].min);
swap(tree[root<<1|1].max,tree[root<<1|1].min);
tree[root<<1].max*=-1;
tree[root<<1].min*=-1;
tree[root<<1|1].max*=-1;
tree[root<<1|1].min*=-1;
}
}
tree[root].neg=0;
}
void push_up(int root)
{
tree[root].max=max(tree[root<<1].max,tree[root<<1|1].max);
tree[root].min=min(tree[root<<1].min,tree[root<<1|1].min);
}
void build(int root,int l,int r)
{
tree[root].l=l;
tree[root].r=r;
tree[root].neg=0;
if(tree[root].l==tree[root].r)
{
tree[root].max=num[l];
tree[root].min=num[l];
tree[root].neg=0;
return;
}
int mid=(l+r)/2;
build(root<<1,l,mid);
build(root<<1|1,mid+1,r);
push_up(root);
}
void update(int root,int pos,int val)
{
if(tree[root].l==tree[root].r)
{
tree[root].max=val;
tree[root].min=val;
return;
}
push_down(root);
int mid=(tree[root].l+tree[root].r)/2;
if(pos<=mid)update(root<<1,pos,val);
else update(root<<1|1,pos,val);
push_up(root);
}
int query(int root,int L,int R)
{
if(L<=tree[root].l&&R>=tree[root].r) return tree[root].max;
push_down(root);
int mid=(tree[root].l+tree[root].r)/2,ret=-INF;
if(L<=mid) ret=max(ret,query(root<<1,L,R));
if(R>mid) ret=max(ret,query(root<<1|1,L,R));
push_up(root);
return ret;
}
void nega(int root,int L,int R)
{
if(L<=tree[root].l&&R>=tree[root].r)
{
tree[root].neg^=1;
swap(tree[root].max,tree[root].min);
tree[root].max*=-1;
tree[root].min*=-1;
return;
}
push_down(root);
int mid=(tree[root].l+tree[root].r)/2;
if(L<=mid) nega(root<<1,L,R);
if(R>mid) nega(root<<1|1,L,R);
push_up(root);
}
void debug(int root)
{
printf("rt=%d [%d~%d] min=%d max=%d neg=%d\n",root,tree[root].l,tree[root].r,tree[root].min
,tree[root].max,(int)tree[root].neg);
if(tree[root].l==tree[root].r) return;
debug(root<<1);
debug(root<<1|1);
}
}tr;
int find(int va,int vb)
{
int f1=top[belong[va]],f2=top[belong[vb]],tmp=-INF;
while(f1!=f2)
{
if(dep[f1]dep[vb]) swap(va,vb);
return max(tmp,tr.query(1,seg[son[va]],seg[vb]));
}
void gao(int va,int vb)
{
int f1=top[belong[va]],f2=top[belong[vb]];
while(f1!=f2)
{
if(dep[f1]dep[vb]) swap(va,vb);
tr.nega(1,seg[son[va]],seg[vb]);
}
int d[maxn][3];
int main()
{
// freopen("cin.txt","r",stdin);
int T;
scanf("%d",&T);
while(T--)
{
init();
scanf("%d",&n);
for(int i=1;i