P3586 [POI2015]LOG

原题链接

考察:树状数组

思路:

        操作1: 将序列的第k个数改为a       很明显的树状数组单点修改

        操作2:在这个序列上,每次选出c个正数,看是否能-s次  这个操作与区间大小无关,也就是所有操作都是在整个序列上进行的.我们需要求出正数的个数,并且求出是否每次能选出c个-1.

        每个操作都是a>=0,所以直接统计个数,求个数可以考虑离散化的树状数组.

        每次都选出c个正数,减s个1.比较直观的想法就是求正数的和,然后>=s即为true.但数据: 正数:898989 1 1 s = 8 即可hack.

        我们把正数>=s与<s的分开考虑.假设有cnt个>=s的正数,这些正数是不用考虑的.if(cnt>=c) puts("TAK"); 

        但是如果cnt<c.我们就要看c-cnt个<s的正数.再用之前直观的想法就是if sum>=s 即为true.从感性上这个结论是正确的,但是理性上本蒟蒻也不知道如何证明

        现在就是求出>=s的正数个数,与<s的正数的和.这个都可以用树状数组完成,但是需要两个.

        检验cnt*s+sum>=c*s.

        不管怎样都TLE了一个点,只能O2优化了

        时间复杂度O(mlog2m+m*log2m)

 

 

 1 #include <iostream> 
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <vector>
 5 using namespace std;
 6 typedef long long LL;
 7 const int N = 3,M = 1000010;
 8 int n,m,last[M];
 9 vector<LL> A;
10 LL tr[2][M];//0求<s的和,1求>=s的个数 
11 char s[N];
12 struct Query{
13     int k,a;
14     bool ask;
15 }q[M];
16 int get(int x)
17 {
18     return lower_bound(A.begin(),A.end(),x)-A.begin()+1;
19 }
20 int lowbit(int x)
21 {
22     return x&-x;
23 }
24 void add(int t,int k,int x)
25 {
26     for(int i=k;i<=M-10;i+=lowbit(i)) tr[t][i]+=x;
27 }
28 LL ask(int t,int x)
29 {
30     LL res = 0;
31     for(int i=x;i;i-=lowbit(i)) res+=tr[t][i];
32     return res;
33 }
34 int main()
35 {
36     scanf("%d%d",&n,&m);
37     for(int i=1;i<=m;i++)
38     {
39         int x,y;
40         scanf("%s%d%d",s,&x,&y);
41         if(s[0]=='U') q[i].k = x,q[i].a = y,q[i].ask = 0;
42         else q[i].k = x,q[i].a = y,q[i].ask = 1;
43         A.push_back(y);
44     }
45     sort(A.begin(),A.end());
46     A.erase(unique(A.begin(),A.end()));
47     for(int i=1;i<=m;i++)
48       if(q[i].ask)//>=s的有多少个. 
49       {//if 
50           int s = get(q[i].a);
51           int sz = ask(0,M-10)-ask(0,s-1);
52           LL sum = ask(1,s-1);//<s的和
53         if((LL)sz*q[i].a+sum>=(LL)q[i].k*q[i].a) puts("TAK") ;
54         else puts("NIE");
55       }else{//将第k个数修改为a 
56           int s = get(q[i].a);
57           if(last[q[i].k])
58           {//上一个数字删去
59               int ns = get(last[q[i].k]);
60               add(0,ns,-1); add(1,ns,-last[q[i].k]);
61         }
62         last[q[i].k] = q[i].a;
63         add(0,s,1); add(1,s,q[i].a);
64       }
65     return 0;
66 }

 

posted @ 2021-05-16 11:55  acmloser  阅读(58)  评论(0编辑  收藏  举报