【bzoj2809】dispatching

这题的最优解法是可并堆,从上往下合并及删点,标准的O(nlogn)解法。

为了练习主席树,特用主席树写一发,可以按dfs序建立主席树,对每个子树进行查询。

总时间5232毫秒,要垫底了...

看来需要去借鉴一下别人的主席树模板了。

/**************************************************************
    Problem: 2809
    User: chad
    Language: C++
    Result: Accepted
    Time:5232 ms
    Memory:98144 kb
****************************************************************/
 
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<iomanip>
#include<map>
#include<queue>
using namespace std;
#define mem1(i,j) memset(i,j,sizeof(i))
#define mem2(i,j) memcpy(i,j,sizeof(i))
#define LL long long
#define up(i,j,n) for(LL i=(j);i<=(n);i++)
#define FILE "dealing"
#define poi vec
#define eps 1e-10
#define mid (l+r>>1)
#define db double
const LL maxn=102000,inf=1000000000,mod=1000000007;
LL read(){
    LL x=0,f=1,ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch<='9'&&ch>='0'){x=(x<<1)+(x<<3)+ch-'0',ch=getchar();}
    return f*x;
}
bool cmax(LL& a,LL b){return a<b?a=b,true:false;}
bool cmin(LL& a,LL b){return a>b?a=b,true:false;}
LL n,m;
struct node{LL y,next;}e[maxn<<1];
int len=0,linkk[maxn<<1],L[maxn],id[maxn],fa[maxn],v[maxn],q[maxn],pre[maxn],t[maxn],low[maxn],dfs_clock=0;
void insert(LL x,LL y){e[++len].y=y;e[len].next=linkk[x];linkk[x]=len;}
LL rt=0;
struct Node{LL x,y,z;}a[maxn];
bool cmp(const Node a,const Node b){return a.x<b.x||(a.x==b.x&&a.y<b.y);}
bool cmp2(const Node a,const Node b){return pre[a.y]<pre[b.y];}
bool cmp3(const Node a,const Node b){return a.y<b.y;}
void dfs(LL x){
    pre[x]=++dfs_clock;
    for(LL i=linkk[x];i;i=e[i].next){
        if(e[i].y==fa[x])continue;
        dfs(e[i].y);
    }
    low[x]=dfs_clock;
}
LL r[2200000],sum[2200000],c[2200000][2],val[2200000],cnt=0;
void updata(LL x){                    //val的和
    sum[x]=sum[c[x][0]]+sum[c[x][1]];
    val[x]=val[c[x][0]]+val[c[x][1]];
}
void set(LL& o,LL rt,LL key,LL l,LL r){
    if(!o)o=++cnt;
    if(l==r){val[o]=a[key].x;sum[o]=1;return;}
    if(key<=mid)c[o][1]=c[rt][1],set(c[o][0],c[rt][0],key,l,mid);
    else c[o][0]=c[rt][0],set(c[o][1],c[rt][1],key,mid+1,r);
    updata(o);
}
 
void init(){up(i,1,n)set(r[i],r[i-1],t[i],1,n);}
 
LL shu=0,y=m,d;
void walk(LL o1,LL o2,LL l,LL r){
    if(val[c[o2][0]]-val[c[o1][0]]<=y)y-=(val[c[o2][0]]-val[c[o1][0]]),shu+=sum[c[o2][0]]-sum[c[o1][0]],d=1;
    else d=0;
    if(l==r)return;
    if(!d)walk(c[o1][0],c[o2][0],l,mid);
    else walk(c[o1][1],c[o2][1],mid+1,r);
}
LL query(LL L,LL R){
    shu=0;y=m;walk(r[L],r[R],1,n);
    return shu;
}
int main(){
    //freopen(FILE".in","r",stdin);
    //freopen(FILE".out","w",stdout);
    n=read(),m=read();
    up(i,1,n){        //薪水         领导力
        fa[i]=read(),v[i]=read(),L[i]=read();
        a[i].x=v[i],a[i].y=i;
        if(!fa[i])rt=i;
        else insert(i,fa[i]),insert(fa[i],i);
    }
    dfs(rt);
    sort(a+1,a+n+1,cmp);
    up(i,1,n)t[pre[a[i].y]]=i;
    up(i,1,n)id[pre[i]]=i;//第i个位置的原节点为id[i]
    init();
    LL ans=0;
    up(i,1,n)ans=max(ans,(LL)query(pre[i]-1,low[i])*L[i]);
    cout<<ans<<endl;
    return 0;
}

  

原文地址:https://www.cnblogs.com/chadinblog/p/6428655.html