【BZOJ4378】[POI2015]Logistyka【树状数组】【结论题】

【题目链接】

题解:

首先得有一个结论:设个数大于s的数字有k个(如果k大于c,显然是TAK。这里讨论k <= c),那么如果个数小于s的数字和不小于(c - k) * s,那么一定有解。

并不会证明...

用树状数组记录一下数字的个数以及数字的数字和,然后判断就可以了。

复杂度:

时间复杂度:O(mlogm),空间复杂度:O(m)。

1A。

GET:

结论题...

/* Telekinetic Forest Guard */
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

typedef long long LL;

const int maxn = 1000005;

int n, m, num[maxn], disc[maxn], tot, trnum[maxn];
LL trsum[maxn];

struct _que {
	int opt, a, b;
} que[maxn];

inline int iread() {
	int f = 1, x = 0; char ch = getchar();
	for(; ch < '0' || ch > '9'; ch = getchar()) f = ch == '-' ? -1 : 1;
	for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
	return f * x;
}

inline int find(int x) {
	int l = 1, r = tot;
	while(l <= r) {
		int mid = l + r >> 1;
		if(disc[mid] < x) l = mid + 1;
		else if(disc[mid] == x) return mid;
		else r = mid - 1;
	}
}

inline void addnum(int x, int c) {
	for(; x <= tot; x += x & -x) trnum[x] += c;
}

inline int querynum(int x) {
	int res = 0;
	for(; x; x -= x & -x) res += trnum[x];
	return res;
}

inline void addsum(int x, int c) {
	for(; x <= tot; x += x & -x) trsum[x] += c;
}

inline LL querysum(int x) {
	LL res = 0;
	for(; x; x -= x & -x) res += trsum[x];
	return res;
}

int main() {
	iread(); m = iread();
	for(int i = 1; i <= m; i++) {
		char ch = getchar(); for(; ch != 'U' && ch != 'Z'; ch = getchar());
		que[i].a = iread(); que[i].b = disc[++tot] = iread();
		que[i].opt = (ch == 'U');
	}

	sort(disc + 1, disc + 1 + tot);
	tot = unique(disc + 1, disc + 1 + tot) - (disc + 1);

	for(int i = 1; i <= m; i++)
		if(que[i].opt == 1) {
			int x = que[i].a, y = find(que[i].b);
			if(!num[x] && que[i].b) addnum(y, 1), n++;
			else if(num[x] && !que[i].b) addnum(y, -1), n--;
			else if(num[x] && que[i].b) addnum(find(num[x]), -1), addnum(y, 1);
			if(num[x]) addsum(find(num[x]), -num[x]);
			if(que[i].b) addsum(y, que[i].b);
			num[x] = que[i].b;
		} else {
			int x = que[i].a, y = find(que[i].b);
			int k = n - querynum(y);
			if(k > x) printf("TAK\n");
			else {
				LL sum = querysum(y);
				printf(sum >= (LL)(x - k) * que[i].b ? "TAK\n" : "NIE\n");
			}
		}

	return 0;
}
时间: 2024-08-27 19:45:12

【BZOJ4378】[POI2015]Logistyka【树状数组】【结论题】的相关文章

【BZOJ4378】[POI2015]Logistyka 树状数组

[BZOJ4378][POI2015]Logistyka 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<=

BZOJ_4378_[POI2015]Logistyka_树状数组

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<=10^9,1<=s<=10^9. Ou

【DFS序+树状数组】HDU 3887 Counting Offspring

http://acm.hdu.edu.cn/showproblem.php?pid=3887 [题意] 给定一棵树,给定这棵树的根 对于每个结点,统计子树中编号比他小的结点个数 编号从小到大一次输出 [思路] 从小到大处理每个结点,即统计当前结点的结果后,把当前结点插入到树状数组中 [AC] 1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 5 const int maxn=1e5+2; 6 c

树状数组和线段树

一.树状数组 在解题过程中,我们有时需要维护一个数组的前缀和 S[i]=A[1]+A[2]+...+A[i] .但是不难发现,如果我们修改了任意一个 A[i],S[i] . S[i+1]...S[n] 都会发生变化.可以说,每次修改 A[i] 后,调整前缀和 S[] 在最坏情况下会需要 O(n) 的时间.当 n 非常大时,程序会运行得非常缓慢.因此,这里我们引入"树状数组",它的修改与求和都是 O(logn) 的,效率非常高. 实现: 对于正整数x,定义lowbit(x)为x的二进制表

[NOI2011]阿狸的打字机 AC自动机+DFS序+树状数组

[NOI2011]阿狸的打字机 Description 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母.经阿狸研究发现,这个打字机是这样工作的: l 输入小写字母,打字机的一个凹槽中会加入这个字母(这个字母加在凹槽的最后).l 按一下印有'B'的按键,打字机凹槽中最后一个字母会消失.l 按一下印有'P'的按键,打字机会在纸上打印出凹槽中现有的所有字母并换行,但凹槽中的字母不会消失.例如,阿狸输入aPaPBbP

POJ 3321 树状数组(+dfs+重新建树)

Apple Tree Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 27092   Accepted: 8033 Description There is an apple tree outside of kaka's house. Every autumn, a lot of apples will grow in the tree. Kaka likes apple very much, so he has been

poj_3321 线段树/树状数组

题目大意 一个果树(每个节点的分叉数目不固定)上有N个分叉点(包括最末的叶节点),则有N-1条边,将分叉点进行从1到N编号,每个分叉点上均可以结水果.开始的时候,每个分叉点都有一个水果,之后进行一系列操作,分为两种操作: (1)Q x: 查询分叉点x以及x的子树上的水果的总数: (2)C x: 更改分叉点x上的结果状态,即原来有水果变为没水果,没水果变为有水果     对于给定的每个Q操作,给出结果. 题目分析 典型的区间操作,但不过是单点更新,区间查询.对于区间操作,可以选用线段树或者树状数组

USACO5.3 IDDFS_强连通_二维树状数组_斐蜀定理_矩形切割

启发式搜索 启发式搜索的主要思想是通过评价一个状态有"多好"来改进对于解的搜索. 方法#1:启发式剪枝 估价函数最简单最普通的用法是进行剪枝.假设有一个求最小代价的一个搜索,使用一个可行的估价函数.如果搜到当前状态时代价为A,这个状态的估价函数是B,那么从这个状态开始搜所能得到的最小代价是A+B.如果当前最优解是C满足C 方法#2:最佳优先搜索 最佳搜索可以看成贪心的深度优先搜索. 与一般搜索随意扩展后继节点不同,最优优先搜索按照估价函数所给的他们的"好坏"的顺序扩

luoguP2184 贪婪大陆 题解(树状数组)

P2184 贪婪大陆  题目 其实很容易理解就是询问一段区间内有多少段不同的区间 然后再仔细思索一下会发现: 1.只要一个区间的开头在一个节点i的左边,那么这个区间包含在区间1~i中. 2.只要一个区间的尾部在一个节点j的左边,那么这个区间肯定不属于j之后的所有区间 这时候就不难想到用两个树状数组维护: 第一个:维护节点i之前有多少个区间的开头 第二个:维护节点j之前有多少个区间的结尾 不难证明拿sum[i]-sum[j]得到的就是i~j中间地雷的个数(手动模拟一波就一清二楚了) #includ