首页 > 代码库 > BZOJ 2809: [Apio2012]dispatching [主席树 DFS序]

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

传送门

题意:查询树上根节点值*子树中权值和$\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].rtypedef 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序]