码迷,mamicode.com
首页 > Windows程序 > 详细

BZOJ 2809: [Apio2012]dispatching [主席树 DFS序]

时间:2017-03-02 19:42:02      阅读:214      评论:0      收藏:0      [点我收藏+]

标签:online   传送门   有根树   printf   权值线段树   for   元素   namespace   多少   

传送门

题意:查询树上根节点值*子树中权值和$\le m$的最大数量 最大值是多少


 

求$DFS$序,然后变成区间中和$\le m$最多有几个元素,建主席树,然后权值线段树上二分就行了

$WA$:又把边表开小了.....

好吧我$zz$了有根树加无向边干什么....

 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define lc(x) t[x].l
#define rc(x) t[x].r
typedef long long ll;
const int N=1e5+5;
int read(){
    char c=getchar();int x=0,f=1;
    while(c<0||c>9){if(c==-)f=-1; c=getchar();}
    while(c>=0&&c<=9){x=x*10+c-0; c=getchar();}
    return x*f;
}
int n,m,mp[N];
struct Ninjia{
    int w,li,id;
    bool operator <(const Ninjia &r)const{return w<r.w;}
}a[N];
inline bool cmpId(Ninjia a,Ninjia b){return a.id<b.id;}
struct Edge{
    int v,ne;
}e[N<<1];
int h[N],cnt;
inline void ins(int u,int v){
    cnt++;
    e[cnt].v=v;e[cnt].ne=h[u];h[u]=cnt;
    cnt++;
    e[cnt].v=u;e[cnt].ne=h[v];h[v]=cnt;
}
int L[N],R[N],dfc,pos[N];
void dfs(int u,int fa){
    L[u]=++dfc; pos[dfc]=u;
    for(int i=h[u];i;i=e[i].ne)
        if(e[i].v!=fa) dfs(e[i].v,u);
    R[u]=dfc;
}

struct Node{
    int l,r,size;
    ll sum;
}t[N*30];
int sz,root[N];
void fIns(int &x,int l,int r,int p){
    t[++sz]=t[x];x=sz;
    t[x].size++;
    t[x].sum+=(ll)mp[p];
    if(l==r) return;
    int mid=(l+r)>>1;
    if(p<=mid) fIns(lc(x),l,mid,p);
    else fIns(rc(x),mid+1,r,p);
}
int fQue(int x,int y,int l,int r,ll m){
    //printf("fQue %d %d %d %d  %d %d %lld %lld\n",x,y,l,r,t[x].size,t[y].size,t[x].sum,t[y].sum);
    if(l==r){
        ll lsum=t[y].sum-t[x].sum;
        return lsum<=m ? t[y].size-t[x].size : 0;
    }else{
        int mid=(l+r)>>1;
        ll lsum=t[lc(y)].sum-t[lc(x)].sum;//printf("lsum %lld %lld\n",lsum,m);
        if(m<=lsum) return fQue(lc(x),lc(y),l,mid,m);
        else return t[lc(y)].size-t[lc(x)].size+fQue(rc(x),rc(y),mid+1,r,m-lsum);
    }
}
int rt=0,u;
int main(){
    freopen("in","r",stdin);
    n=read();m=read();
    for(int i=1;i<=n;i++){
        u=read();if(u==0) rt=i;
        ins(u,i),a[i].w=read(),a[i].li=read(),a[i].id=i;
    }
    sort(a+1,a+1+n);
    for(int i=1;i<=n;i++) mp[i]=a[i].w,a[i].w=i;
    sort(a+1,a+1+n,cmpId);
    //for(int i=1;i<=n;i++) printf("a %d %d %d\n",a[i].id,a[i].w,mp[a[i].w]);
    dfs(rt,0);
    //for(int i=1;i<=n;i++) printf("LR %d %d %d\n",i,L[i],R[i]);
    //for(int i=1;i<=n;i++) printf("%d ",pos[i]);puts("");
    for(int i=1;i<=n;i++) root[i]=root[i-1],fIns(root[i],1,n,a[pos[i]].w);
    ll ans=0;
    for(int i=1;i<=n;i++) ans=max(ans,(ll)a[i].li*fQue(root[L[i]-1],root[R[i]],1,n,m));
    printf("%lld",ans);
}

 

BZOJ 2809: [Apio2012]dispatching [主席树 DFS序]

标签:online   传送门   有根树   printf   权值线段树   for   元素   namespace   多少   

原文地址:http://www.cnblogs.com/candy99/p/6491960.html

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