题目描述
维护一个长度为n的序列,一开始都是0,支持以下两种操作:1.U k a 将序列中第k个数修改为a。2.Z c s 在这个序列上,每次选出c个正数,并将它们都减去1,询问能否进行s次操作。每次询问独立,即每次询问不会对序列进行修改。
输入输出格式
输入格式:
第一行包含两个正整数n,m(1<=n,m<=1000000),分别表示序列长度和操作次数。接下来m行为m个操作,其中1<=k,c<=n,0<=a<=10^9,1<=s<=10^9。
输出格式:
包含若干行,对于每个Z询问,若可行,输出TAK,否则输出NIE。
输入输出样例
说明
维护一个长度为n的序列,一开始都是0,支持以下两种操作:
1.U k a 将序列中第k个数修改为a。
2.Z c s 在这个序列上,每次选出c个正数,并将它们都减去1,询问能否进行s次操作。
每次询问独立,即每次询问不会对序列进行修改。
我们分情况考虑:
若设大于等于s的数为cnt个
1、cnt >= c 我们直接选这c个就好了
2、cnt < c 这样不够选,那么我们考虑先选这cnt个大于等于s的数。那么要用其他的数来补上剩余的(c - cnt) * s。所以至少要求小于s的数的和是要大于(c - cnt) * s的。那么是不是满足小于s的数的和大于(c - cnt) * s的数列就一定满足条件呢?答案是肯定的。(可以感性理解2333)设想如果用贪心策略每一次都取出c个最大的数做减法的话我们一定可以平均把(c - cnt) * s分摊到每一个小于s的数上。
#include<cstdio> #include<algorithm> #define int long long using namespace std; const int maxn = 1e6 + 5; int n, m, a, b, num[maxn], N = 1e9 + 5; char s[2]; namespace SGT { struct node {int ch[2], sf[2];}tree[maxn * 10]; int cnt, root; void push_up(int rt) { tree[rt].sf[0] = tree[tree[rt].ch[0]].sf[0] + tree[tree[rt].ch[1]].sf[0]; tree[rt].sf[1] = tree[tree[rt].ch[0]].sf[1] + tree[tree[rt].ch[1]].sf[1]; } void insert(int p, int tl, int tr, int dt, int & rt) { if(!rt) rt = ++cnt; if(tl == tr) { tree[rt].sf[0] += p * dt; tree[rt].sf[1] += dt; return; } int mid = tl + tr >> 1; if(p <= mid) insert(p, tl, mid, dt, tree[rt].ch[0]); else insert(p, mid + 1, tr, dt, tree[rt].ch[1]); push_up(rt); } int query(int l, int r, int id, int tl, int tr, int rt) { if(!rt) return 0; if(tl == l && tr == r) return tree[rt].sf[id]; int mid = tl + tr >> 1; if(r <= mid) return query(l, r, id, tl, mid, tree[rt].ch[0]); else if(mid < l) return query(l, r, id, mid + 1, tr, tree[rt].ch[1]); else { return query(l, mid, id, tl, mid, tree[rt].ch[0]) + query(mid + 1, r, id, mid + 1, tr, tree[rt].ch[1]); } } } int sum, cnt; signed main() { scanf("%d%d", &n, &m); for(register int i = 1; i <= m; ++i) { scanf("%s%d%d", s, &a, &b); if(s[0] == 'U') { if(num[a]) SGT::insert(num[a], 1, N, -1, SGT::root); if(b) SGT::insert(b, 1, N, 1, SGT::root); num[a] = b; } else { sum = SGT::query(1, b - 1, 0, 1, N, SGT::root); cnt = SGT::query(b, N, 1, 1, N, SGT::root); printf("%s\n", sum >= (a - cnt) * b ? "TAK" : "NIE"); } } return 0; }
没有帐号? 立即注册