码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ4009 [HNOI2015]接水果

时间:2016-03-03 22:40:46      阅读:382      评论:0      收藏:0      [点我收藏+]

标签:

AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=4009

 

打了一会儿的整体二分了...于是就准备好了做这道题。

具体题解不想讲了,看看别人的就好:http://blog.csdn.net/thy_asdf/article/details/50363672

然后注意二维平面上其实我们是舍弃了一部分点的,就是类似要求横坐标一定要小于纵坐标这种...这样就不会算重或者算漏了...

上面这个的代码 就是if(x>y) swap(x,y)?...好吧诸如此类..

 

敲了比较久,感觉比较顺,结果发现样例都不能过?!然后我检查很久觉得二分没错之后,调试啊调试,检查啊检查,结果发现原来是树状数组的区间加减打挂了[以前都是打线段树,不过今天觉得树状数组常数这么小,还是要复习一下的吧...结果一打就挂...],后来发现是单点修改,所以只要一个简单的差分就好了...改完之后就A了

不过复杂度貌似和同机房的同学不一样?...我的是二分答案,他们的说是二分选哪个篮子,其实相当于离散化?...

反正最后他们的快一些...不过感觉我这个模板感觉很靠谱,我就不改了...反正复杂度是能过的就行了。

 

技术分享
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

inline int in(){
    int x=0;char ch=getchar();
    while(ch>9 || ch<0) ch=getchar();
    while(ch>=0 && ch<=9) x=x*10+ch-0,ch=getchar();
    return x;
}

const int maxn=40010;
const int INF=0x3f3f3f3f;

struct Node{
    int data,next;
}node[maxn<<1];

#define now node[point].data
#define then node[point].next

struct Query{
    int tp,x,y,k,cur,rk;
}q[maxn*6],q1[maxn*6],q2[maxn*6];

int n,m,P,Idex;
int tot,cnt;
int b[maxn];
int tmp[maxn*6],ans[maxn];
int head[maxn],dfn[maxn],low[maxn];
int f[maxn][16],d[maxn];

void add_edge(int u,int v){
    node[cnt].data=v;node[cnt].next=head[u];head[u]=cnt++;
    node[cnt].data=u;node[cnt].next=head[v];head[v]=cnt++;
}

void dfs(int x){
    dfn[x]=++Idex;
    for(int i=1;i<=15;i++)
        f[x][i]=f[f[x][i-1]][i-1];
    for(int point=head[x];point!=-1;point=then)
        if(now!=f[x][0])
            f[now][0]=x,d[now]=d[x]+1,dfs(now);
    low[x]=Idex;
}

int LCA(int x,int y){
    int tmp=d[x]-d[y];
    for(int i=15;i>=0;i--)
        if(tmp&(1<<i)) x=f[x][i];
    if(x==y) return x;
    for(int i=15;i>=0;i--)
        if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
    return f[x][0];
}

int get_fa(int x,int k){
    for(int i=0;i<=15;i++)
        if((1<<i)&k) x=f[x][i];
    return x;
}

void add2(int x,int d){
    for(int i=x;i<=n;i+=i&-i) b[i]+=d;
}

void add(int l,int r,int d){
    add2(l,d),add2(r+1,-d);    
}

int ask(int x){
    int sum=0;
    for(int i=x;i;i-=i&-i) sum+=b[i];
    return sum;
}

void div(int H,int T,int l,int r){
    if(H>T) return ;
    if(l==r){
        for(int i=H;i<=T;i++)
            if(q[i].tp==3) ans[q[i].y]=l;
        return ;
    }
    int mid=(l+r)>>1;
    for(int i=H;i<=T;i++){
        if(q[i].tp==1 && q[i].k<=mid) add(q[i].x,q[i].y,1);
        else if(q[i].tp==2 && q[i].k<=mid) add(q[i].x,q[i].y,-1);
        else if(q[i].tp==3)
            tmp[i]=ask(q[i].x);
    }
    for(int i=H;i<=T;i++){
        if(q[i].tp==1 && q[i].k<=mid) add(q[i].x,q[i].y,-1);
        else if(q[i].tp==2 && q[i].k<=mid) add(q[i].x,q[i].y,1);
    }
    int l1=0,l2=0;
    for(int i=H;i<=T;i++){
        if(q[i].tp==3){
            if(q[i].cur+tmp[i]>=q[i].k) q1[++l1]=q[i];
            else q[i].cur+=tmp[i],q2[++l2]=q[i];
        }
        else{
            if(q[i].k<=mid) q1[++l1]=q[i];
            else q2[++l2]=q[i];
        }
    }
    for(int i=1;i<=l1;i++) q[H+i-1]=q1[i];
    for(int i=1;i<=l2;i++) q[H+l1+i-1]=q2[i];
    div(H,H+l1-1,l,mid);
    div(H+l1,T,mid+1,r);
}

bool cmp(const Query &A,const Query &B){
    if(A.rk!=B.rk) return A.rk<B.rk;
    return A.tp<B.tp;
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("fruit.in","r",stdin);
    freopen("fruit.out","w",stdout);
#endif

    int u,v,v1,w;

    n=in();P=in();m=in();
    for(int i=1;i<=n;i++) head[i]=-1;
    for(int i=1;i<n;i++)
        u=in(),v=in(),add_edge(u,v);
    dfs(1);
    for(int i=1;i<=P;i++){
        u=in(),v=in(),w=in();
        if(d[u]>d[v]) swap(u,v);
        if(LCA(v,u)==u){
            v1=get_fa(v,d[v]-d[u]-1);
            q[++tot].tp=1,q[tot].rk=1,q[tot].x=dfn[v],q[tot].y=low[v],q[tot].k=w;
            q[++tot].tp=2,q[tot].rk=dfn[v1],q[tot].x=dfn[v],q[tot].y=low[v],q[tot].k=w;
            if(low[v1]+1<=n){
                q[++tot].tp=1,q[tot].rk=dfn[v],q[tot].x=low[v1]+1,q[tot].y=n,q[tot].k=w;
                q[++tot].tp=2,q[tot].rk=low[v]+1,q[tot].x=low[v1]+1,q[tot].y=n,q[tot].k=w;
            }
        }
        else{
            if(dfn[u]<dfn[v]) swap(u,v);
            q[++tot].tp=1,q[tot].rk=dfn[v],q[tot].x=dfn[u],q[tot].y=low[u],q[tot].k=w;
            q[++tot].tp=2,q[tot].rk=low[v]+1,q[tot].x=dfn[u],q[tot].y=low[u],q[tot].k=w;
        }
    }
    for(int i=1;i<=m;i++){
        u=in(),v=in();
        if(dfn[u]<dfn[v]) swap(u,v);
        q[++tot].rk=dfn[v],q[tot].x=dfn[u];
        q[tot].tp=3,q[tot].y=i,q[tot].k=in();
    }
    sort(q+1,q+tot+1,cmp);
    div(1,tot,0,INF);
    for(int i=1;i<=m;i++)
        printf("%d\n",ans[i]);
    return 0;
}
View Code

 

BZOJ4009 [HNOI2015]接水果

标签:

原文地址:http://www.cnblogs.com/Robert-Yuan/p/5240209.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!