poj3237tree【树链剖分入门题+线段树】

休息了两天,今天开始做树链剖分,除了模板长以外,还是挺好理解的。就只是线段树+剖分独特的函数,然后树链剖分所用的数组有点多,没了。其中需要注意的一个点是“链”(路径)不一定是从根节点到叶子节点的,轻儿子这个点它也有重儿子啊啊啊。

再说这个题,单点更新,区间取相反数,区间求最大值。

/***********
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


你可能感兴趣的:(—数据结构,———树套树)