[POI2015]LOG(树状数组)

今天考试考了这题,所以来贡献\([POI2015]LOG\)的第一篇题解。代码略丑,调了快三个小时才调出来\(AC\)代码。

对于这种小清新数据结构题,所以我觉得树状数组才是这道题的正确打开方式。

首先离散化,这样才不会爆内存。开两个树状数组,第一个树状数组记录离散化后\(1\)\(i\)中数字出现的个数,第二个树状数组离散化前\(1\)\(i\)数字出现值的和。把所有询问都读入进来,对于每次操作:

操作\(1\):单点修改,若之前的数是正数,第一个树状数组\(-1\),第二个树状数组\(-\)原来的数,若之后的数是正数,第一个树状数组\(+1\),第二个树状数组\(+\)之后的数

操作\(2\):区间询问,先将大于\(s\)的个数求出来,再比较\(c-\)大于\(s\)的个数乘上\(c\)与剩余数之和,若前者大,输出\(NIE\),否则输出\(TAK\)

再开一个数组记录当前序列的值,就完事了

\(Code\ Below:\)

#include <bits/stdc++.h>
#define ll long long
#define res register
using namespace std;
const ll maxn=1000000+10;
ll n,m,a[maxn],b[maxn],mp[maxn],tot,num;
//a[i]是目前的序列情况,b[i]是第几次修改后离散化1-num,mp记录离散化后的数组1-1e9
//tot是几次修改,num是离散化后的修改,c1[i]是1-i的个数,c2[i]是1-i的值的和 
ll c1[maxn],c2[maxn];
struct node{
	ll k,x,id;
}q[maxn];
//id是第几次修改 
inline ll read(){
	res ll x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
	return (f==1)?x:-x;
}
ll lowbit(ll x){return x & (-x);}
void add_num(ll x,ll y){
	for(;x<maxn;x+=lowbit(x))
		c1[x]+=y;	
}
void add_sum(ll x,ll y){
	for(;x<maxn;x+=lowbit(x))
		c2[x]+=y;
}
ll query_num(ll x){
	ll ans=0;
	for(;x>0;x-=lowbit(x))
		ans+=c1[x];
	return ans;
}
ll query_sum(ll x){
	ll ans=0;
	for(;x>0;x-=lowbit(x))
		ans+=c2[x];
	return ans;
}

int main()
{
	n=read(),m=read();
	res ll k,x,c,s;char ch=getchar();
	for(ll i=1;i<=m;i++){
		while(ch!='U'&&ch!='Z') ch=getchar();
		q[i].k=read(),q[i].x=read();
		if(ch=='U') {
			q[i].id=++tot;
			b[tot]=mp[tot]=q[i].x;
		}
		else q[i].id=-1;
		if(i!=m) ch=getchar();
	}
	sort(mp+1,mp+tot+1);
	num=unique(mp+1,mp+tot+1)-mp-1;
	for(ll i=1;i<=tot;i++)
		b[i]=lower_bound(mp+1,mp+num+1,b[i])-mp;
	for(ll i=1;i<=m;i++)
		if(q[i].id!=-1) q[i].x=b[q[i].id];
	for(ll i=1;i<=m;i++){
		if(q[i].id!=-1){//q[i].x被离散化 
			if(a[q[i].k]>0){
				ll real=lower_bound(mp+1,mp+num+1,a[q[i].k])-mp;
				add_num(real+1,-1);
				add_sum(real+1,-a[q[i].k]);
			}
			a[q[i].k]=mp[q[i].x];
			if(mp[q[i].x]>0){
				add_num(q[i].x+1,1);
				add_sum(q[i].x+1,mp[q[i].x]);
			}
		}
		else {//q[i].x没被离散化,real是去q[i].x在mp中的位置 
			ll real=upper_bound(mp+1,mp+num+1,q[i].x)-mp-1;
			ll bigans=query_num(maxn+1)-query_num(real+1);
			ll smallans=query_sum(real+1);
			if(smallans>=(q[i].k-bigans)*q[i].x) printf("TAK\n");
			else printf("NIE\n");
		}
	}
	return 0;
}
posted @ 2018-08-25 18:04  Owen_codeisking  阅读(565)  评论(1编辑  收藏  举报