某一天马学长给我看了一个lca的题目,然而确实是lca+树上差分,但是仅仅有lca和树上差分解决不了,然后我就去面向题解编程了。
可是这个线段树合并是个什么东东。。。
然而今天看书,突然看到了这个线段树合并。
就写一下了。
%mmh。

P4556 [Vani有约会]雨天的尾巴:
题目背景
深绘里一直很讨厌雨天。
灼热的天气穿透了前半个夏天,后来一场大雨和随之而来的洪水,浇灭了一切。
虽然深绘里家乡的小村落对洪水有着顽固的抵抗力,但也倒了几座老房子,几棵老树被连根拔起,以及田地里的粮食被弄得一片狼藉。
无奈的深绘里和村民们只好等待救济粮来维生。
不过救济粮的发放方式很特别。

题目描述
首先村落里的一共有n座房屋,并形成一个树状结构。然后救济粮分m次发放,每次选择两个房屋(x,y),然后对于x到y的路径上(含x和y)每座房子里发放一袋z类型的救济粮。
然后深绘里想知道,当所有的救济粮发放完毕后,每座房子里存放的最多的是哪种救济粮。

输入格式
第一行两个正整数n,m,含义如题目所示。
接下来n-1行,每行两个数(a,b),表示(a,b)间有一条边。
再接下来m行,每行三个数(x,y,z),含义如题目所示。

输出格式
n行,第i行一个整数,表示第i座房屋里存放的最多的是哪种救济粮,如果有多种救济粮存放次数一样,输出编号最小的。
如果某座房屋里没有救济粮,则对应一行输出0。

输入输出样例
输入 #1 复制
5 3
1 2
3 1
3 4
5 3
2 3 3
1 5 2
3 3 3
输出 #1 复制
2
3
3
0
2
说明/提示
对于20%的数据,1 <= n, m <= 100
对于50%的数据,1 <= n, m <= 2000
对于100%的数据,1 <= n, m <= 100000, 1 <= a, b, x, y <= n, 1 <= z <= 100000
Vani

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<queue>
#define ll long long
#define llu unsigned ll
using namespace std;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const ll lnf=0x3f3f3f3f3f3f3f3f;
const int maxn=100100;
struct node
{
    int lc,rc;
    int maxx,pos;
}t[maxn*20*4];

int f[maxn][20],root[maxn],d[maxn],ans[maxn];
int head[maxn],ver[maxn*2],nt[maxn*2];
int xx[maxn],yy[maxn],zz[maxn],b[maxn];
int tot=1,n,m,tt,cnt=0,pm;

void add(int x,int y)
{
    ver[++tot]=y,nt[tot]=head[x],head[x]=tot;
}

void bfs(void)
{
    queue<int>q;
    q.push(1);
    d[1]=1;
    while(q.size())
    {
        int x=q.front();
        q.pop();
        for(int i=head[x];i;i=nt[i])
        {
            int y=ver[i];
            if(d[y]) continue;
            d[y]=d[x]+1;
            q.push(y);

            f[y][0]=x;
            for(int j=1;j<=tt;j++)
                f[y][j]=f[f[y][j-1]][j-1];
        }
    }
}

int lca(int x,int y)
{
    if(d[x]>d[y]) swap(x,y);
    for(int i=tt;i>=0;i--)
        if(d[f[y][i]]>=d[x]) y=f[y][i];

    if(x==y) return x;

    for(int i=tt;i>=0;i--)
        if(f[y][i]!=f[x][i]) x=f[x][i],y=f[y][i];
    return f[x][0];
}

int build(void)
{
    ++cnt;
    t[cnt].lc=t[cnt].rc=t[cnt].maxx=t[cnt].pos=0;
    return cnt;
}

void pushup(int p)
{
    t[p].maxx=max(t[t[p].lc].maxx,t[t[p].rc].maxx);
    t[p].pos=t[t[p].lc].maxx>=t[t[p].rc].maxx?t[t[p].lc].pos:t[t[p].rc].pos;
}

void _insert(int p,int l,int r,int pos,int val)
{
    if(l==r)
    {
        t[p].maxx+=val;
        t[p].pos=t[p].maxx>0?l:0;
        return ;
    }
    int mid=(l+r)>>1;
    if(pos<=mid)
    {
        if(!t[p].lc) t[p].lc=build();
        _insert(t[p].lc,l,mid,pos,val);
    }
    else
    {
        if(!t[p].rc) t[p].rc=build();
        _insert(t[p].rc,mid+1,r,pos,val);
    }
    pushup(p);
}

int _merge(int p,int q,int l,int r)
{
    if(!p) return q;
    if(!q) return p;
    if(l==r)
    {
        t[p].maxx+=t[q].maxx;
        t[p].pos=t[p].maxx>0?l:0;
        return p;
    }
    int mid=(l+r)>>1;
    t[p].lc=_merge(t[p].lc,t[q].lc,l,mid);
    t[p].rc=_merge(t[p].rc,t[q].rc,mid+1,r);
    pushup(p);
    return p;
}

void dfs(int x,int fa)
{
    for(int i=head[x];i;i=nt[i])
    {
        int y=ver[i];
        if(y==fa) continue;
        dfs(y,x);
        root[x]=_merge(root[x],root[y],1,pm);
    }
    ans[x]=t[root[x]].pos;
}

int main(void)
{
    scanf("%d%d",&n,&m);
    tt=log(n)/log(2)+1;

    int x,y;
    for(int i=1;i<n;i++)
    {
        scanf("%d%d",&x,&y);
        add(x,y),add(y,x);
    }
    for(int i=1;i<=m;i++)
        scanf("%d%d%d",&xx[i],&yy[i],&zz[i]),b[i]=zz[i];

    bfs();
    sort(b+1,b+m+1);
    pm=unique(b+1,b+m+1)-(b+1);

    for(int i=1;i<=n;i++) root[i]=build();

    for(int i=1;i<=m;i++)
        zz[i]=lower_bound(b+1,b+pm+1,zz[i])-b;


    for(int i=1;i<=m;i++)
    {
        int fa=lca(xx[i],yy[i]);
        _insert(root[xx[i]],1,pm,zz[i],1);
        _insert(root[yy[i]],1,pm,zz[i],1);
        _insert(root[fa],1,pm,zz[i],-1);
        if(f[fa][0]) _insert(root[f[fa][0]],1,pm,zz[i],-1);
    }
    dfs(1,0);

    for(int i=1;i<=n;i++)
        printf("%d\n",b[ans[i]]);

    return 0;
}