bzoj 4378: [POI2015]Logistyka &&luogu 3586

4378: [POI2015]Logistyka

Time Limit: 20 Sec   Memory Limit: 256 MB
Submit: 557   Solved: 277
[ Submit][ Status][ Discuss]

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。

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

HINT

鸣谢Claris

Source


这题感觉有点骚

模型转化不是难点吧

模型抽象出来就是要维护>=一个值的个数

和小于一个值的所有值sum

先把值域离散化一下

然后开两个值域上的树状数组(分别维护个数和sum)

每次插入时在离散化后的值上+1,同时如果该位置已经修改过了,要把上次操作的值的位置-1

然后在另一个树状数组上加上原来的值,同时减去上次操作的值(如果有的话)

#include<cstdio>
#include<algorithm>
#include<cstring>
inline int lowbit(int x)
{
	return x&(-x);
}
inline int read()
{
	int ans=0,f=1;char t=getchar();
	while(t<'0'||t>'9')	f=(t=='-'?-1:1),t=getchar();
	while(t>='0'&&t<='9')	ans=ans*10+t-'0',t=getchar();
	return ans*f;
}
int cnt;
const int N=1e6+7;
struct bit_node
{
	long long c[N];
	inline void modify(int x,int num)
	{
		for(int i=x;i<=cnt;i+=lowbit(i))	c[i]+=num;
	}
	inline long long query(int x)
	{
		long long ans=0;
		for(int i=x;i;i-=lowbit(i))	ans+=c[i];
		return ans;
	}
}bit1,bit2;
inline char readchar()
{
	char t=getchar();
	while(t<'A'||t>'Z')	t=getchar();
	return t;
}
char au[N];
int bi[N],aa[N];
struct node
{
	int v,order;
}e[N];
inline bool cmp(node a,node b)
{
	return a.v<b.v;
}
inline bool cmp2(node a,node b)
{
	return a.order<b.order;
}
int bo[N];
int main()
{
//	freopen("in.txt","r",stdin);
	int n=read(),m=read();
	for(int i=1;i<=m;i++)
	{
		au[i]=readchar();
		bi[i]=read();e[i].v=read(),e[i].order=i;
	}
	std::sort(e+1,e+1+m,cmp);
	cnt=0;aa[e[1].order]=++cnt;
	for(int i=2;i<=m;i++)
	if(e[i].v==e[i-1].v)	aa[e[i].order]=cnt;
	else aa[e[i].order]=++cnt;
	
	std::sort(e+1,e+1+m,cmp2);
	int ans=0;
	for(int i=1;i<=m;i++)
	if(au[i]=='U')
	{
		if(!bo[bi[i]])	
		{
			bo[bi[i]]=i,bit1.modify(aa[i],1);
			bit2.modify(aa[i],e[i].v);
		}
		else	
		{
			int j=bo[bi[i]];
			bit1.modify(aa[j],-1);bit1.modify(aa[i],1);
			bit2.modify(aa[j],-e[j].v);bit2.modify(aa[i],e[i].v);
			bo[bi[i]]=i;
		}
	}
	else
	{
		long long sum=bit1.query(cnt);
		sum-=bit1.query(aa[i]-1);
		bool flag=0;
		if(bi[i]<=sum)	flag=1;
		else
		{
			sum=bi[i]-sum;
			if(bit2.query(aa[i]-1)>=(long long)sum*e[i].v)	flag=1;
		}
		if(flag==1)	printf("TAK\n");
		else printf("NIE\n");
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值