zoukankan      html  css  js  c++  java
  • [noi1994]海盗

    令$a_{i,j}(jle i)$表示第i个人的方案中给第j个人$a_{i,j}$的钱,有以下性质:
    1.如果第j个人一定同意(否则就会死)第i个人的方案,那么$a_{i,j}=0$(容易发现一定同意的人就是在上一个不是-1之后的人)
    2.否则$a_{i,j}=1+max_{1le t<i}a_{t,j}$,尽量选择最小的,当无法成立就令$a_{i,j}=0$
    那么这个过程初始是$a_{1}=k$,然后每一次操作包含以下几步:
    初始的a是上一次可以通过的方案,之间死的人都是-1(这样+1刚好为0)
    求出a中前$v[i]-1$小的和+$v[i]-1$与$k$判断,如果小于等于k即可行,剩下的钱就是i本身的
    如果可行,删除不是前$v[i]-1$小的点,并加入等量的0,然后打一个全局的$tag+=1$标记
    这个过程用平衡树维护即可(权值线段树内存不够) 
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 2000005
     4 #define ll long long
     5 #define pii pair<int,int>
     6 #define fi first
     7 #define se second 
     8 #define s(p) son[k][p]
     9 int V,n,r,x,tag,tot[N],sz[N],ra[N],son[N][2];
    10 ll k,ans,a[N],f[N];
    11 void up(int k){
    12     sz[k]=sz[s(0)]+sz[s(1)]+tot[k];
    13     f[k]=1LL*a[k]*tot[k]+f[s(0)]+f[s(1)];
    14 }
    15 void rotate(int &k,int u,int p){
    16     s(p)=son[u][p^1];
    17     son[u][p^1]=k;
    18     up(k);
    19     k=u;
    20 }
    21 void add(int &k,ll x,int y){
    22     if (!k){
    23         k=++V;
    24         a[k]=f[k]=x;
    25         ra[k]=rand();
    26     }
    27     if (a[k]==x){
    28         tot[k]+=y;
    29         up(k);
    30         return;
    31     }
    32     bool p=(a[k]<x);
    33     add(s(p),x,y);
    34     if (ra[s(p)]<ra[k])rotate(k,s(p),p);
    35     up(k);
    36 }
    37 ll query(int k,int x){
    38     if (!k)return 0;
    39     if (x<=sz[s(0)])return query(s(0),x);
    40     if (x<=sz[s(0)]+tot[k])return f[s(0)]+1LL*a[k]*(x-sz[s(0)]);
    41     return f[s(0)]+1LL*a[k]*tot[k]+query(s(1),x-sz[s(0)]-tot[k]);
    42 }
    43 void del(int &k,int x){
    44     if (!k)return;
    45     if (x<=sz[s(0)])del(k=s(0),x);
    46     else
    47         if (x>sz[s(0)]+tot[k])del(s(1),x-sz[s(0)]-tot[k]);
    48         else{
    49             tot[k]-=sz[s(0)]+tot[k]-x;
    50             s(1)=0;
    51         }
    52     up(k);
    53 }
    54 int main(){
    55     scanf("%d%lld",&n,&k);
    56     for(int i=1;i<=n;i++){
    57         scanf("%d",&x);
    58         ans=max(k-(query(r,x-1)+(x-1LL)*(tag+1)),-1LL);
    59         if (ans!=-1){
    60             int s=sz[r]-(x-1);
    61             del(r,x-1);
    62             tag++;
    63             add(r,-tag,s);
    64         }
    65         add(r,ans-tag,1);
    66         printf("%lld
    ",ans);
    67     }
    68 } 
    View Code
  • 相关阅读:
    容斥原理算法总结(bzoj 2986 2839)
    网络流系列算法总结(bzoj 3438 1061)
    bzoj 2746: [HEOI2012]旅行问题 AC自动机fail树
    bzoj 3283: 运算器 扩展Baby Step Giant Step && 快速阶乘
    计算几何考场绘图技巧
    bzoj 1845: [Cqoi2005] 三角形面积并 扫描线
    bzoj 3784: 树上的路径 堆维护第k大
    BZOJ 1231: [Usaco2008 Nov]mixup2 混乱的奶牛
    BZOJ 1112: [POI2008]砖块Klo
    BZOJ 1003: [ZJOI2006]物流运输trans DP+最短路
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/13159094.html
Copyright © 2011-2022 走看看