hdu 6162 Ch’s gift(主席树)

来源:互联网 发布:linux yum jdk 1.8 编辑:程序博客网 时间:2024/06/06 01:52

Mr. Cui is working off-campus and he misses his girl friend very much. After a whole night tossing and turning, he decides to get to his girl friend’s city and of course, with well-chosen gifts. He knows neither too low the price could a gift be since his girl friend won’t like it, nor too high of it since he might consider not worth to do. So he will only buy gifts whose price is between [a,b].
There are n cities in the country and (n-1) bi-directional roads. Each city can be reached from any other city. In the ith city, there is a specialty of price ci Cui could buy as a gift. Cui buy at most 1 gift in a city. Cui starts his trip from city s and his girl friend is in city t. As mentioned above, Cui is so hurry that he will choose the quickest way to his girl friend(in other words, he won’t pass a city twice) and of course, buy as many as gifts as possible. Now he wants to know, how much money does he need to prepare for all the gifts?
Input
There are multiple cases.

For each case:
The first line contains tow integers n,m(1≤n,m≤10^5), representing the number of cities and the number of situations.
The second line contains n integers c1,c2,…,cn(1≤ci≤10^9), indicating the price of city i’s specialty.
Then n-1 lines follows. Each line has two integers x,y(1≤x,y≤n), meaning there is road between city x and city y.
Next m line follows. In each line there are four integers s,t,a,b(1≤s,t≤n;1≤a≤b≤10^9), which indicates start city, end city, lower bound of the price, upper bound of the price, respectively, as the exact meaning mentioned in the description above
Output
Output m space-separated integers in one line, and the ith number should be the answer to the ith situation.
Sample Input
5 3
1 2 1 3 2
1 2
2 4
3 1
2 5
4 5 1 3
1 1 1 1
3 5 2 3
Sample Output
7 1 4

给你一棵树n个点,每个点有个值,m个询问,每个询问都会有 起点终点上界下界,让你求在此上下界内所有的礼物的总和

第一次在限时赛写主席树= = 写的非常干净帅气啊 半小时就写完啦。。他么的 交了一发wa了,就慌了= =其实只是因为每次没有清空fa数组。。导致求lca的时候wa了。。。。。。但是那时候不知道这个原因。。一直纠结哪里错了。。试了好久没找到错误。。加了fa试了一发。。mle。。。我就又开始怀疑刚才是不是刚开始把数组多+了10导致的。。其实不是啊。。是因为本来就应该mle的啊。。。
后来队友帮我找mle原因。。发现自己太浪了。。瞎几把开数组。。全开了3e5,很多1e5就行了的。。然后两点半纠结到4点半 MLE了好多发终于过了 沃日

我的做法是把边界也离散化了 开了 3*600万的数组。。按理说 65536kb应该放不下,,可是。。跑了发现连60000kb都不到。。就这么神奇。
而且这题数据都这么水。。很多人暴力过的。。我第一个自己现场做的主席树啊。。不开心。。。

我的做法是建立一颗离散化后得所有点的数,每次往里面加具体的值,利用has[l]加值

//晚上想到其实不用离散边界。。左边界其实就是lower_bound 就行没有任何影响,而右边界。。loweer_bound 以后判定右边界比has的值小的话 -1 就好
而且改良以后完全就可以在线处理了,内存也变成了 3*200万

#include <bits/stdc++.h>using namespace std;const int maxn = 3e5+10;typedef long long ll;int a[100010];vector<int> e[100010];int n,m;int fa[100010][20];int b[maxn],tsize,tot,root[100010],dep[100010];int ls[300010*20],rs[300010*20];ll sum[300010*20];int has[300010];void pushup(int now){    sum[now]=sum[ls[now]]+sum[rs[now]];}struct node{    int u,v;    int l,r;}no[100010];void update(int pre,int &now,int l,int r,int d){    now=++tot;    ls[now]=ls[pre];    rs[now]=rs[pre];    sum[now]=sum[pre];    if(l==r&&l==d)    {        sum[now]+=has[l];        return ;    }    int mid=(l+r)>>1;    if(d<=mid) update(ls[pre],ls[now],l,mid,d);    else if(d>mid) update(rs[pre],rs[now],mid+1,r,d);    pushup(now);}int build(int l,int r){    int rot=++tot;    sum[rot]=0;    if(l==r)        return rot;    int mid=(l+r)>>1;    ls[rot]=build(l,mid);    rs[rot]=build(mid+1,r);    return rot;}void hash1(){    sort(b+1,b+1+n);    has[1]=b[1];    int ff=1;    for(int i=2;i<=n;i++)        if(b[i]!=b[i-1]) has[++ff]=b[i];     tsize=unique(b+1,b+1+n)-b-1;}int find_index(int x){    return lower_bound(b+1,b+1+tsize,x)-b;}void dfs(int x,int y){    update(root[y],root[x],1,tsize,find_index(a[x]));    dep[x]=dep[y]+1;    for(int i=0;i<e[x].size();i++)    {        if(e[x][i]==y) continue;        int vv=e[x][i];        fa[vv][0]=x;         for(int j=1;fa[fa[vv][j-1]][j-1];j++)            fa[vv][j]=fa[fa[vv][j-1]][j-1];        dfs(vv,x);    }}int lca(int x,int y){    if(dep[x]<dep[y])swap(x,y);    int t=dep[x]-dep[y];    for(int i=0;i<=19;i++)        if((1<<i)&t)x=fa[x][i];    for(int i=19;i>=0;i--)        if(fa[x][i]!=fa[y][i])            x=fa[x][i],y=fa[y][i];    if(x==y)return x;    return fa[x][0];}ll query(int l1,int r1,int zuxian,int zuzu,int L,int R,int l,int r){    if(L<=l&&R>=r)    {        return (sum[l1]+sum[r1]-sum[zuxian]-sum[zuzu]);    }    ll re=0;    int mid=(l+r)>>1;    if(L<=mid) re+=query(ls[l1],ls[r1],ls[zuxian],ls[zuzu],L,R,l,mid);    if(R>mid) re+=query(rs[l1],rs[r1],rs[zuxian],rs[zuzu],L,R,mid+1,r);     return re;}int main(){    while(~scanf("%d%d",&n,&m))    {        tot=0;        memset(fa,0,sizeof(fa));        for(int i=1;i<=n;i++)        {            scanf("%d",&a[i]);            b[i]=a[i];        }                for(int i=1;i<=n;i++)        e[i].clear();        for(int i=1;i<n;i++)        {            int u,v;            scanf("%d%d",&u,&v);            e[u].push_back(v);            e[v].push_back(u);        }        for(int i=1;i<=m;i++)        {            scanf("%d%d%d%d",&no[i].u,&no[i].v,&no[i].l,&no[i].r);            b[++n]=no[i].l,b[++n]=no[i].r;        }        hash1();        dep[0]=0;        root[0]=build(1,tsize);        dfs(1,0);        for(int i=1;i<=m;i++)        {            int lc=lca(no[i].u,no[i].v);            printf("%lld%c",query(root[no[i].u],root[no[i].v],root[lc],root[fa[lc][0]],find_index(no[i].l),find_index(no[i].r),1,tsize),(i==m)?'\n':' ');            }    }    return 0;}

改良版本的

#include <bits/stdc++.h>using namespace std;const int maxn = 3e5+10;typedef long long ll;int a[100010];vector<int> e[100010];int n,m;int fa[100010][20];int b[maxn],tsize,tot,root[100010],dep[100010];int ls[100010*20],rs[100010*20];ll sum[100010*20];int has[300010];void pushup(int now){    sum[now]=sum[ls[now]]+sum[rs[now]];}struct node{    int u,v;    int l,r;}no[100010];void update(int pre,int &now,int l,int r,int d){    now=++tot;    ls[now]=ls[pre];    rs[now]=rs[pre];    sum[now]=sum[pre];    if(l==r&&l==d)    {        sum[now]+=has[l];        return ;    }    int mid=(l+r)>>1;    if(d<=mid) update(ls[pre],ls[now],l,mid,d);    else if(d>mid) update(rs[pre],rs[now],mid+1,r,d);    pushup(now);}int build(int l,int r){    int rot=++tot;    sum[rot]=0;    if(l==r)        return rot;    int mid=(l+r)>>1;    ls[rot]=build(l,mid);    rs[rot]=build(mid+1,r);    return rot;}void hash1(){    sort(b+1,b+1+n);    has[1]=b[1];    int ff=1;    for(int i=2;i<=n;i++)        if(b[i]!=b[i-1]) has[++ff]=b[i];     tsize=unique(b+1,b+1+n)-b-1;}int find_index(int x){    return lower_bound(b+1,b+1+tsize,x)-b;}void dfs(int x,int y){    update(root[y],root[x],1,tsize,find_index(a[x]));    dep[x]=dep[y]+1;    for(int i=0;i<e[x].size();i++)    {        if(e[x][i]==y) continue;        int vv=e[x][i];        fa[vv][0]=x;         for(int j=1;fa[fa[vv][j-1]][j-1];j++)            fa[vv][j]=fa[fa[vv][j-1]][j-1];        dfs(vv,x);    }}int lca(int x,int y){    if(dep[x]<dep[y])swap(x,y);    int t=dep[x]-dep[y];    for(int i=0;i<=19;i++)        if((1<<i)&t)x=fa[x][i];    for(int i=19;i>=0;i--)        if(fa[x][i]!=fa[y][i])            x=fa[x][i],y=fa[y][i];    if(x==y)return x;    return fa[x][0];}ll query(int l1,int r1,int zuxian,int zuzu,int L,int R,int l,int r){    if(L<=l&&R>=r)    {        return (sum[l1]+sum[r1]-sum[zuxian]-sum[zuzu]);    }    ll re=0;    int mid=(l+r)>>1;    if(L<=mid) re+=query(ls[l1],ls[r1],ls[zuxian],ls[zuzu],L,R,l,mid);    if(R>mid) re+=query(rs[l1],rs[r1],rs[zuxian],rs[zuzu],L,R,mid+1,r);     return re;}int main(){    while(~scanf("%d%d",&n,&m))    {        tot=0;        memset(fa,0,sizeof(fa));        for(int i=1;i<=n;i++)        {            scanf("%d",&a[i]);            b[i]=a[i];        }                for(int i=1;i<=n;i++)        e[i].clear();        for(int i=1;i<n;i++)        {            int u,v;            scanf("%d%d",&u,&v);            e[u].push_back(v);            e[v].push_back(u);        }        hash1();        dep[0]=0;        root[0]=build(1,tsize);        dfs(1,0);        for(int i=1;i<=m;i++)        {            int aa,bb,cc,dd;            scanf("%d%d%d%d",&aa,&bb,&cc,&dd);            int lc=lca(aa,bb);            int zuo=find_index(cc);            int you=find_index(dd);            if(dd<b[you]) you--;            printf("%lld%c",query(root[aa],root[bb],root[lc],root[fa[lc][0]],zuo,you,1,tsize),(i==m)?'\n':' ');            }    }    return 0;}