@description@

维护一个长度为 n 的序列,一开始都是 0,支持以下两种操作:

1.U k a 将序列中第 k 个数修改为 a。

2.Z c s 在这个序列上,每次选出 c 个正数,并将它们都减去 1,询问能否进行 s 次操作。

每次询问独立,即每次询问不会对序列进行修改。

input

第一行包含两个正整数 n, m (1<=n, m<=1000000),分别表示序列长度和操作次数。

接下来 m 行为 m 个操作,其中 1<=k, c<=n,0<=a<=109,1<=s<=109。

output

包含若干行,对于每个 Z 询问,若可行,输出 TAK,否则输出 NIE。

sample input

3 8

U 1 5

U 2 7

Z 2 6

U 3 1

Z 2 6

U 2 2

Z 2 6

Z 2 1

sample output

NIE

TAK

NIE

TAK

@solution@

如果序列中的某个数 x > s,因为我们只进行 s 次 -1 的操作,这个数能用到的部分只有 s 这么多。

所以我们可以将序列中所有大于 s 的数修改成 s。

询问能够成立的必要条件是序列所有数之和 >= c*s。

而可以发现,当我们将大于 s 的数修改成 s 过后,如上的条件就变成了充要条件。

证明的话可以使用归纳法。

首先可以发现,每次操作至少保留 c 个正数。分类讨论等于 s 的数的个数:

(1)若等于 s 的数 >= c,显然成立(直接拿这几个数进行操作)。

(2)若等于 s 的数 < c,我们保证选出的 c 个数包含这些等于 s 的数。这样操作完后依然满足所有数之和 >= c*(s-1)且所有数<=(s-1),就可以归纳证明了。

至于实现,我们并不需要真的把所有大于 s 的数修改成 s,只需要统计大于 s 的数的个数再乘上 s 即可。

可以用平衡树维护,也可以用离散化 + 线段树维护。

@accepted code@

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int MAXN = 1000000;
struct query{
int type, x, y;
}qry[MAXN + 5];
int a[MAXN + 5], d[MAXN + 5];
int n, m, dcnt;
void discrete() {
sort(d+1, d+dcnt+1);
dcnt = unique(d+1, d+dcnt+1) - d - 1;
for(int i=1;i<=m;i++)
if( !qry[i].type )
qry[i].y = lower_bound(d+1, d+dcnt+1, qry[i].y) - d;
}
struct node{
int le, ri;
ll sum; int cnt;
}tree[4*MAXN + 5];
void pushup(int x) {
tree[x].sum = tree[x<<1].sum + tree[x<<1|1].sum;
tree[x].cnt = tree[x<<1].cnt + tree[x<<1|1].cnt;
}
void build(int x, int l, int r) {
tree[x].le = l, tree[x].ri = r;
tree[x].sum = tree[x].cnt = 0;
if( l == r ) {
if( l == 1 ) tree[x].cnt = n;
return ;
}
int mid = (l + r) >> 1;
build(x<<1, l, mid);
build(x<<1|1, mid+1, r);
pushup(x);
}
void modify(int x, int p, int k) {
if( p > tree[x].ri || p < tree[x].le )
return ;
if( tree[x].le == tree[x].ri ) {
tree[x].sum += k*d[tree[x].le];
tree[x].cnt += k;
return ;
}
modify(x<<1, p, k);
modify(x<<1|1, p, k);
pushup(x);
}
ll s; int c;
void query(int x, int p) {
if( d[tree[x].ri] <= p ) s += tree[x].sum;
else if( d[tree[x].le] > p ) c += tree[x].cnt;
else query(x<<1, p), query(x<<1|1, p);
}
char cmd[2];
int main() {
d[dcnt = 1] = 0;
scanf("%d%d", &n, &m);
for(int i=1;i<=m;i++) {
scanf("%s%d%d", cmd, &qry[i].x, &qry[i].y);
if( cmd[0] == 'U' )
qry[i].type = 0, d[++dcnt] = qry[i].y;
else qry[i].type = 1;
}
discrete(); build(1, 1, dcnt);
for(int i=1;i<=n;i++)
a[i] = 1;
for(int i=1;i<=m;i++) {
if( !qry[i].type ) {
modify(1, a[qry[i].x], -1);
a[qry[i].x] = qry[i].y;
modify(1, a[qry[i].x], 1);
}
else {
s = c = 0; query(1, qry[i].y);
puts(1LL*qry[i].x*qry[i].y <= s + 1LL*c*qry[i].y ? "TAK" : "NIE");
}
}
}

@details@

一开始找了一个比较复杂的结论,还涉及到线段树上二分等诡异的操作。

大概一两个月过后再去看……这什么玩意儿啊……我怎么看不懂我写了啥啊……

然后翻看题解才看到了这个比较简单的结论。

@bzoj - 4378@ [POI2015] Logistyka的更多相关文章

  1. bzoj 4378: [POI2015]Logistyka ——树桩数组+离散化

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

  2. @bzoj - 4378@ [POI2015] Pustynia

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定一个长度为 n 的正整数序列 a,每个数都在 1 到 10^ ...

  3. [POI2015]Logistyka

    [POI2015]Logistyka 题目大意: 一个长度为\(n(n\le10^6)\)的数列\(A_i\),初始全为\(0\).操作共\(m(m\le10^6)\)次,包含以下两种: 将\(A_x ...

  4. 【BZOJ4378】[POI2015]Logistyka 树状数组

    [BZOJ4378][POI2015]Logistyka Description 维护一个长度为n的序列,一开始都是0,支持以下两种操作:1.U k a 将序列中第k个数修改为a.2.Z c s 在这 ...

  5. bzoj 4386: [POI2015]Wycieczki

    bzoj 4386: [POI2015]Wycieczki 这题什么素质,爆long long就算了,连int128都爆……最后还是用long double卡过的……而且可能是我本身自带大常数吧,T了 ...

  6. BZOJ 4385: [POI2015]Wilcze doły

    4385: [POI2015]Wilcze doły Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 648  Solved: 263[Submit][ ...

  7. BZOJ 4384: [POI2015]Trzy wieże

    4384: [POI2015]Trzy wieże Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 217  Solved: 61[Submit][St ...

  8. Bzoj 3747: [POI2015]Kinoman 线段树

    3747: [POI2015]Kinoman Time Limit: 60 Sec  Memory Limit: 128 MBSubmit: 553  Solved: 222[Submit][Stat ...

  9. BZOJ 3747 POI2015 Kinoman 段树

    标题效果:有m点,每个点都有一个权值.现在我们有这个m为点的长度n该序列,寻求区间,它仅出现一次在正确的点区间内值和最大 想了很久,甚至神标题,奔说是水的问题--我醉了 枚举左点 对于每个请求留点右键 ...

随机推荐

  1. js对象类型判断工具

    对象类型判断工具 /** *类功能:对象类型判断工具 **/ var TypeUtil = { /** *方法说明:是否是数组 **/ isArray: function (obj) {//是否是数组 ...

  2. 【模板】倍增LCA [2017年5月计划 清北学堂51精英班 Day3]

    P3379 [模板]最近公共祖先(LCA) 题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询 ...

  3. 用js控制video的src_百度知道

    代码如下 <section id="player"> <video id="media" width="100%" hei ...

  4. ListView设置的点点滴滴

    去掉ListView的分界线 1. ListView的属性Divider设为#FFCC00      这种对任何背景都适用 2. 把ListView的属性Divider设为和背景一样的颜色 3.and ...

  5. python 中初始化二维数组的方法

    最好的方法是: 初始化4*3的二维数组 a = [[0 for col in xrange(3)] for row in xrange(4)] 而不可以用: a = [[0]*3]*4 [0]*3是生 ...

  6. LintCode刷题笔记-- Edit distance

    标签:动态规划 描述: Given two words word1 and word2, find the minimum number of steps required to convert wo ...

  7. GDOI模拟4.11~4.13总结

    总体情况 省选前的第一场模拟,就连续三天垫底滚粗了. 三天下来,只做了第一天的签到题,然后再做了一些水题的暴力,还不得分. 三天分数:100/400+40/400+90/400=230/1200,得了 ...

  8. 前端与编译原理——用JS写一个JS解释器

    说起编译原理,印象往往只停留在本科时那些枯燥的课程和晦涩的概念.作为前端开发者,编译原理似乎离我们很远,对它的理解很可能仅仅局限于"抽象语法树(AST)".但这仅仅是个开头而已.编 ...

  9. MaxCompute 构建企业云数据仓库CDW的最佳实践建议

    在本文中阿里云资深产品专家云郎分享了基于阿里云 MaxCompute 构建企业云数据仓库CDW的最佳实践建议. 本文内容根据演讲视频以及PPT整理而成. 大家下午好,我是云郎,之前在甲骨文做企业架构师 ...

  10. MySQL数据库操作语句(补充1)(cmd环境运行)

    一.字符串类型 enum枚举类型 /* 也叫做枚举类型,类似于单选! 如果某个字段的值只能从某几个确定的值中进行选择,一般就使用enum类型, 在定义的时候需要将该字段所有可能的选项都罗列出来: */ ...