BZOJ4378: [POI2015]Logistyka

n<=1e6个数字,开始都是0,m<=1e6个操作:1、把第x个数修改成y;2、询问:对序列中的数字进行c次操作,每次选s个正数把他们-1,问能否进行。

一个数字Ai,如果Ai>=s,那它可以被选中s次;如果Ai<s,那就Ai次。设k个数字大于等于s,小于s的数字的和是sum,只需要:sum<=(c-k)*s就一定可以完成操作。正确性证明:如果sum<(c-k)*s,那根本不够操作,必要;如果sum>=(c-k)*s,每次选最大的那几个数-1即可。

因此只需要维护大于等于某个数字的个数和小于某个数字的数的和,这些可以把询问离线后离散化,树状数组维护即可。

ps:离散化后加个unique效果更佳!!

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<stdlib.h>
 4 //#include<assert.h>
 5 #include<math.h>
 6 #include<algorithm>
 7 //#include<iostream>
 8 using namespace std;
 9 
10 int n,m;
11 #define maxn 1000011
12 #define LL long long
13 struct BIT
14 {
15     LL a[maxn];int n;
16     void clear(int n) {memset(a,0,sizeof(a));this->n=n;}
17     void add(int x,LL v) {for (;x<=n;x+=x&-x) a[x]+=v;}
18     LL query(int x) {LL ans=0;for (;x;x-=x&-x) ans+=a[x];return ans;}
19 }tv,tc;
20 int lisan[maxn],num[maxn];
21 struct Doo
22 {
23     char s[3];int x,y;
24 }doo[maxn];
25 bool isdigit(char c) {return c>='0' && c<='9';}
26 int qread()
27 {
28     char c;int s=0;while (!isdigit(c=getchar()));
29     do s=s*10+c-'0'; while (isdigit(c=getchar()));return s;
30 }
31 int main()
32 {
33     scanf("%d%d",&n,&m);
34     for (int i=1;i<=m;i++)
35     {
36         scanf("%s",doo[i].s);doo[i].x=qread(),doo[i].y=qread();
37         lisan[i]=doo[i].y;
38     }
39     sort(lisan+1,lisan+1+m);
40     tv.clear(m); tc.clear(m);
41     memset(num,0,sizeof(num));
42     for (int i=1;i<=m;i++)
43     {
44         if (doo[i].s[0]=='U')
45         {
46             if (num[doo[i].x]>0)
47             {
48                 int pos=lower_bound(lisan+1,lisan+1+m,num[doo[i].x])-lisan;
49                 tv.add(pos,-num[doo[i].x]);
50                 tc.add(m-pos+1,-1);
51             }
52             num[doo[i].x]=doo[i].y;
53             int pos=lower_bound(lisan+1,lisan+1+m,doo[i].y)-lisan;
54             tv.add(pos,doo[i].y);
55             tc.add(m-pos+1,1);
56         }
57         else
58         {
59             int pos=lower_bound(lisan+1,lisan+1+m,doo[i].y)-lisan;
60             printf(tv.query(pos-1)>=(doo[i].x-tc.query(m-pos+1))*1ll*doo[i].y?"TAK
":"NIE
");
61         }
62     }
63     return 0;
64 }
View Code
原文地址:https://www.cnblogs.com/Blue233333/p/7685053.html