zoukankan      html  css  js  c++  java
  • 洛谷 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;
    }
    
  • 相关阅读:
    Create方法失效而没有提示错误信息
    JS弹出窗口控制
    本周活动
    JavaScript的初步了解
    关于PHP接收文件的资料
    mvc模式改进网站结构
    一周动态
    排序
    Java的内存泄漏
    Android笔记
  • 原文地址:https://www.cnblogs.com/sdlang/p/13068309.html
Copyright © 2011-2022 走看看