洛谷 P3586 [POI2015]LOG

维护一个长度为n的序列,一开始都是0,支持以下两种操作:1.U k a 将序列中第k个数修改为a。2.Z c s 在这个序列上,每次选出c个正数,并将它们都减去1,询问能否进行s次操作。每次询问独立,即每次询问不会对序列进行修改。

这个题看起来很nb的样子

首先我们可以把询问转化一下

既然要进行s次,那么那些大于等于s是一定要选的,假设这些数有cnt个

再考虑比s小的,假设这些数的和为sum,有x个

那么我们要满足(sumge (c-cnt) imes s)这个条件

看起来很正确但又感觉少了点什么QAQ,我们来证明一下

因为和已经满足条件了,那么我们只需要知道每次选的数是不是能有c个就可以,也就是(xge c-cnt)

考虑c最少的情况,也就是(sum=sum s-1)

那么(x=frac{sum}{s-1}),所以(frac{sum}{s-1}ge c-cnt)

移项得到(sumge (c-cnt) imes (s-1))

而根据原式(sumge (c-cnt) imes s),上面这个结论就已经成立啦QAQ

所以我们只需要维护比一个数大的数有多少个,比一个数小的数的值的和就可以了

对于这个题而言,我们可以选择离散化+树状数组

Code

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define LL long long
const int N = 1e6;
using namespace std;
struct node
{
    int opt,c,s;
}q[N + 5];
int n,m,a[N + 5],data[N + 5],c[N + 5],mp[N + 5],na[N + 5];
LL s[N + 5];
char ch;
int lowbit(int x)
{
    return x & (-x);
}
void addc(int k,int x)
{
    if (k == 0)
        return;
    for (;k <= m;k += lowbit(k))
        c[k] += x;
}
void adds(int k,int x)
{
    if (k == 0)
        return;
    for (;k <= m;k += lowbit(k))
        s[k] += x;
}
int queryc(int k)
{
    int ans = 0;
    for (;k;k -= lowbit(k))
        ans += c[k];
    return ans;
}
LL querys(int k)
{
    LL ans = 0;
    for (;k;k -= lowbit(k))
        ans += s[k];
    return ans;
}
int main()
{
    scanf("%d%d",&n,&m);
    for (int i = 1;i <= m;i++)
    {
        cin>>ch;
        scanf("%d%d",&q[i].c,&q[i].s);
        data[i] = q[i].s;
        if (ch == 'U')
            q[i].opt = 1;
        else
            q[i].opt = 2;
    }
    sort(data + 1,data + m + 1);
    for (int i = 1;i <= m;i++)
        mp[i] = lower_bound(data + 1,data + m + 1,q[i].s) - data,na[mp[i]] = q[i].s;
    for (int i = 1;i <= m;i++)
    {
        if (q[i].opt == 1)
        {
            addc(a[q[i].c],-1);
            adds(a[q[i].c],-na[a[q[i].c]]);
            a[q[i].c] = mp[i];
            addc(a[q[i].c],1);
            adds(a[q[i].c],q[i].s);
        }
        else
        {
            int cnt = queryc(m) - queryc(mp[i] - 1);
            if (querys(mp[i] - 1) >= 1ll * q[i].s * (q[i].c - cnt))
                printf("TAK
");
            else
                printf("NIE
");
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/sdlang/p/13068309.html