码迷,mamicode.com
首页 > 其他好文 > 详细

[noi1994]海盗

时间:2020-06-18 19:48:12      阅读:53      评论:0      收藏:0      [点我收藏+]

标签:alt   hid   fir   print   技术   权值线段树   删除   tag   bit   

令$a_{i,j}(j\le i)$表示第i个人的方案中给第j个人$a_{i,j}$的钱,有以下性质:
1.如果第j个人一定同意(否则就会死)第i个人的方案,那么$a_{i,j}=0$(容易发现一定同意的人就是在上一个不是-1之后的人)
2.否则$a_{i,j}=1+\max_{1\le 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\n",ans);
67     }
68 } 
View Code

 

[noi1994]海盗

标签:alt   hid   fir   print   技术   权值线段树   删除   tag   bit   

原文地址:https://www.cnblogs.com/PYWBKTDA/p/13159094.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!