• [APIO2012]派遣 洛谷P1552 bzoj2809 codevs1763


    http://www.codevs.cn/problem/1763/

    https://www.lydsy.com/JudgeOnline/problem.php?id=2809

    https://www.luogu.org/problemnew/show/P1552

    http://210.33.19.101/problem/2182

    用线段树合并,值域线段树维护可重集合,线段树每个节点维护一个sum表示当前集合中,所有在范围[l,r](这个点的值域区间)内的数的和;每个点从其子节点合并;查询就根据左子节点sum与当前最大允许的和决定往左还是往右走

    话说稍微有点卡空间。。。(加了内存回收,然而理论上内存回收应该并不能改进最坏空间复杂度)

    看了题解,发现只要暴力启发式合并/可并堆,合并完成后暴力删除最大值直到合法就行了。。。(因为每个点只会被删一次)

    又想了想,只要暴力普通堆启发式合并就行了。。。。40行就行。。。

     1 #pragma GCC optimize(3)//不开优化可能被卡常
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<queue>
     5 #include<vector>
     6 #define pb push_back
     7 using namespace std;
     8 typedef long long LL;
     9 int n,m;
    10 vector<int> ch[100100];
    11 int c[100100],l[100100],fa[100100];
    12 LL sum[100100];
    13 priority_queue<int> q[100100];
    14 LL ans;
    15 void dfs(int u)
    16 {
    17     int i,v;
    18     q[u].push(c[u]);sum[u]+=c[u];
    19     for(i=0;i<ch[u].size();i++)
    20     {
    21         v=ch[u][i];
    22         dfs(v);
    23         if(q[v].size()>q[u].size())    swap(q[u],q[v]);
    24         while(!q[v].empty())    q[u].push(q[v].top()),q[v].pop();
    25         sum[u]+=sum[v];
    26     }
    27     while(sum[u]>m)    sum[u]-=q[u].top(),q[u].pop();
    28     ans=max(ans,l[u]*LL(q[u].size()));
    29 }
    30 int main()
    31 {
    32     int i,a;
    33     scanf("%d%d",&n,&m);
    34     for(i=1;i<=n;i++)
    35     {
    36         scanf("%d%d%d",&a,&c[i],&l[i]);
    37         fa[i]=a;ch[a].pb(i);
    38     }
    39     dfs(1);
    40     printf("%lld",ans);
    41     return 0;
    42 }

    空间因为pq里面用了vector之类的好像会被卡。。。可以改一下

     1 #pragma GCC optimize(3)//不开优化可能被卡常
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<queue>
     5 #include<vector>
     6 #define pb push_back
     7 using namespace std;
     8 typedef long long LL;
     9 int n,m;
    10 vector<int> ch[100100];
    11 int c[100100],l[100100],fa[100100];
    12 LL sum[100100];
    13 priority_queue<int> *q[100100];
    14 LL ans;
    15 void dfs(int u)
    16 {
    17     int i,v;q[u]=new priority_queue<int>();
    18     q[u]->push(c[u]);sum[u]+=c[u];
    19     for(i=0;i<ch[u].size();i++)
    20     {
    21         v=ch[u][i];
    22         dfs(v);
    23         if(q[v]->size()>q[u]->size())    swap(q[u],q[v]);
    24         while(!q[v]->empty())    q[u]->push(q[v]->top()),q[v]->pop();
    25         sum[u]+=sum[v];delete q[v];
    26     }
    27     while(sum[u]>m)    sum[u]-=q[u]->top(),q[u]->pop();
    28     ans=max(ans,l[u]*LL(q[u]->size()));
    29 }
    30 int main()
    31 {
    32     int i,a;
    33     scanf("%d%d",&n,&m);
    34     for(i=1;i<=n;i++)
    35     {
    36         scanf("%d%d%d",&a,&c[i],&l[i]);
    37         fa[i]=a;ch[a].pb(i);
    38     }
    39     dfs(1);
    40     printf("%lld",ans);
    41     return 0;
    42 }

    错误记录:答案没有开longlong所以无限WA

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<vector>
     4 #define pb push_back
     5 using namespace std;
     6 typedef long long LL;
     7 namespace S
     8 {
     9 #define mid (l+((r-l)>>1))
    10 #define N 3000000
    11 int dat[N],lc[N],rc[N];LL sum[N];
    12 int L;
    13 int st[N+100],top;
    14 void init()
    15 {
    16     int i;
    17     for(i=1;i<N;i++) st[++top]=i;
    18 }
    19 int getnode()
    20 {
    21     int t=st[top--];dat[t]=sum[t]=lc[t]=rc[t]=0;
    22     return t;
    23 }
    24 void delnode(int x) {st[++top]=x;}
    25 void _addx(int l,int r,int &num)
    26 {
    27     if(!num)    num=getnode();
    28     if(l==r)    {dat[num]++;sum[num]+=l;return;}
    29     if(L<=mid)   _addx(l,mid,lc[num]);
    30     else    _addx(mid+1,r,rc[num]);
    31     dat[num]=dat[lc[num]]+dat[rc[num]];
    32     sum[num]=sum[lc[num]]+sum[rc[num]];
    33 }
    34 void addx(int p,int &num)
    35 {
    36     L=p;_addx(1,1e9,num);
    37 }
    38 int merge(int a,int b)
    39 {
    40     if(!a||!b)  return a+b;
    41     lc[a]=merge(lc[a],lc[b]);
    42     rc[a]=merge(rc[a],rc[b]);
    43     dat[a]+=dat[b];
    44     sum[a]+=sum[b];
    45     delnode(b);
    46     return a;
    47 }
    48 int find(int l,int r,int num,LL msum)
    49 {
    50     if(l==r)    return msum/l;
    51     if(sum[lc[num]]>=msum)   return find(l,mid,lc[num],msum);
    52     else    return find(mid+1,r,rc[num],msum-sum[lc[num]])+dat[lc[num]];
    53 }
    54 #undef mid
    55 }
    56 vector<int> ch[200100];
    57 int n,m;
    58 int c[200100],l[200100],fa[200100];
    59 int rt[200100];LL ans;
    60 void dfs(int u)
    61 {
    62     S::addx(c[u],rt[u]);
    63     for(int i=0,v;i<ch[u].size();i++)
    64     {
    65         v=ch[u][i];
    66         dfs(v);
    67         rt[u]=S::merge(rt[u],rt[v]);
    68     }
    69     ans=max(ans,LL(l[u])*S::find(1,1e9,rt[u],m));
    70 }
    71 int main()
    72 {
    73     int i,a;S::init();
    74     scanf("%d%d",&n,&m);
    75     for(i=1;i<=n;i++)
    76     {
    77         scanf("%d%d%d",&a,&c[i],&l[i]);
    78         fa[i]=a;ch[a].pb(i);
    79     }
    80     dfs(1);
    81     printf("%lld",ans);
    82     return 0;
    83 }
  • 相关阅读:
    开启gpu加速的高性能移动端相框组件!
    一看就懂得移动端rem布局、rem如何换算
    加密算法
    YDNKJS 笔记
    JavaScript函数
    测试下
    console前端代码自动删除QQ空间我的说说
    前端规范
    解决方案
    重读js高程笔记二
  • 原文地址:https://www.cnblogs.com/hehe54321/p/9035162.html
Copyright © 2020-2023  润新知