Luogu_P3586_POI2015_LOG

树状数组 yyds#

题意#

给定一个序列,支持两种操作:

  • 修改: 把第 k 个数字改为 x
  • 查询: 是否可以找到 c 个大于 1 的数字,并把他们都减去 1, 执行 k

注: 每次查询不影响原序列的值

Trick#

对于查询来说,如果某个数字的个数 Xk ,那么这个数字就可以执行 k 次 减去 1 的操作,那么我们每此选出的 c 个数字都都可以有 X
假设这样的数字有 cnt 个,那么我们只需要在 个数 <k 的数字之中选择,满足每此找到 ccnt 个数字 把他们减去 1, 执行 k
经过证明可以得知,如果这样的数字的个数是 CNT(ccnt)k 那么我们就可以执行这个操作 k 次。

实现#

我们可以先离散化一下,然后用两个树状数组,一个维护有多少种数字,另一个维护数字的个数

Solution#

#include <bits/stdc++.h>
#define fi first    
#define se second    
#define pb push_back
#define mk make_pair
#define leng(a) (int)a.size()
#define lowbit(x) (x&-x)
#define fix(a) fixed << setprecision(a) 
#define debug(x) cout<<#x" ----> "<<x<<endl
#define rep(i, b, s) for(int i = (b); i <= (s); ++i)
#define pre(i, b, s) for(int i = (b); i >= (s); --i)
#define TEST int T; read(T); while(T --) 

//#define int long long 
#define endl '\n' 
#define ios ios::sync_with_stdio(false); cin.tie(0), cout.tie(0)
#define all(v) (v).begin(),(v).end()

using namespace std;
 
typedef unsigned long long ULL;
typedef pair<int, int> PII ;
typedef pair<int, PII> PIII ;// {value, {value, value}}
typedef pair<double, double> PDD ;
typedef long long LL;
const int INF = INT_MAX;
const LL INFF = INT64_MAX;
const int MOD = 998244353;
const double eps = 1e-10;
const double pi = acos(-1.0);
   
LL gcd(LL a, LL b) {return b ? gcd(b, a%b) : a;}
inline LL ksm(LL a, LL b) {if (b == 0) return 1; LL ns = ksm(a, b >> 1); ns = ns * ns % MOD; if (b & 1) ns = ns * a % MOD; return ns;}
inline LL lcm(LL a, LL b) {return a / gcd(a, b) * b;}
inline void out(bool flag);
template <typename T> void chkmax(T &x, T y) { x = max(x, y); }
template <typename T> void chkmin(T &x, T y) { x = min(x, y); }
template <typename T> inline T mod(T &x) {return x % MOD;}
inline bool valid(char c) { return 33<=c&&c<=126; }
template < typename T >
inline void read(T &x)
{
    x = 0; bool f = 0; char ch = getchar();
    while(!isdigit(ch)){f ^= !(ch ^ 45);ch=getchar();}
    while(isdigit(ch)) x= (x<<1)+(x<<3)+(ch&15),ch=getchar();
    x = f ? -x : x;
}
template<typename T,typename ...Args>void read(T &x, Args &...args)
{ read(x),read(args...); }
inline void reads(char *s) {
    int l=0;char c;
    while(!valid(s[0]=getchar()));
    while(valid(s[++l]=getchar()));
}
int n, m;
const int N = 2e6 + 10;
int a[N];
LL tr[N][2];
int op[N];
PII query[N];
int mx;
vector<int> ALL;
void add(int a, int b, int id) {
    while(a <= mx) {
        tr[a][id] += b;
        a += lowbit(a);
    }
}
LL sum(int a, int id) {
    LL res = 0;
    while(a) {
        res += tr[a][id];
        a -= lowbit(a);
    }
    return res;
}
inline void solve() {
    read(n, m);
    rep(i, 1, m) {
        char OP[3];
        reads(OP);
        int X, Y; read(X, Y);
        query[i] = {X, Y};
        if(*OP == 'U') op[i] = 1;
        else op[i] = 2;
        ALL.pb(X); ALL.pb(Y);
    }
    sort(all(ALL));
    ALL.erase(unique(all(ALL)), ALL.end());
    mx = ALL.size();
    function <int(int)> find =  [&] (int x) { return lower_bound(all(ALL), x) - ALL.begin() + 1;};
    rep(i, 1, m) {
        int id = op[i];
        int l = query[i].fi, r = query[i].se;
        int L = find(l), R = find(r);
        // tr[][0] 代表的是个数
        // tr[][1] 代表的是和
        // 我们需要的是 >= R 的数字的个数  以及 < R 的数字的和  
        if(id == 1) {
            int last = a[L];
            int res = find(last);
            if(last > 0) 
                add(res, -1, 0), add(res, -last, 1);
            if(r > 0) 
                add(R, 1, 0), add(R, r, 1);

            a[L] = r;
        } else {
            int cnt = sum(mx, 0) - sum(R - 1, 0);
            if(cnt >= l) puts("TAK");
            else {
                LL ans = sum(R - 1, 1);
                if(1LL * (l - cnt) * r <= ans) puts("TAK");
                else puts("NIE");
            }
        }
    }
}
 
signed main() 
{

    solve();
 
    return 0;
}
 
 
inline void out(bool flag) {
    if(flag) puts("YES");
    else puts("NO");
}
posted @   ccz9729  阅读(29)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示
主题色彩