标签: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