题目:
题意:
我们需要支持两个操作,单点修改以及区间询问每次从不同的位置 − c -c −c,问是否能重复 s s s次
分析:
这题的难点就在于区间询问的分析,当一个询问能被满足,当且仅当满足两个条件任意一个:
1.
1.
1.大于等于
s
s
s的位置
>
=
c
>=c
>=c
2.
2.
2.小于
s
s
s的数的和
>
=
c
−
>=c-
>=c−大于等于
s
s
s的个数
∗
s
*s
∗s
所以我们可以用两个树状数组来维护个数和和
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<queue>
#include<map>
#define LL long long
using namespace std;
inline LL read()
{
LL s=0,f=1; char c=getchar();
while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9') {s=s*10+c-'0';c=getchar();}
return s*f;
}
char op[1000005];
LL c[1000005],s[1000005],bc[1000005],a[1000005],mm;
struct Tree{
LL w[1000005];
void add(LL k,LL x)
{
for(;k<=mm;k+=k&(-k)) w[k]+=x;
return;
}
LL query(LL k)
{
LL sum=0;
for(;k;k=k&(k-1)) sum+=w[k];
return sum;
}
}t1,t2;
int main()
{
// freopen("book.in","r",stdin);
// freopen("book.out","w",stdout);
LL n=read(),m=read();
for(LL i=1;i<=m;i++)
{
op[i]=getchar();
while(op[i]!='U'&&op[i]!='Z') op[i]=getchar();
c[i]=read();bc[i]=s[i]=read();
}
sort(bc+1,bc+1+m);
mm=unique(bc+1,bc+1+m)-bc-1;
for(LL i=1;i<=m;i++)
{
LL ss=lower_bound(bc+1,bc+1+mm,s[i])-bc;
if(op[i]=='U')
{
if(a[c[i]]) t1.add(a[c[i]],-1),t2.add(a[c[i]],-bc[a[c[i]]]);
t1.add(ss,1);t2.add(ss,bc[ss]);
a[c[i]]=ss;
}
else
{
LL z=t1.query(mm)-t1.query(ss-1);
if(z>=c[i]) {printf("TAK\n");continue;}
LL w=t2.query(ss-1);
if(w>=(c[i]-z)*bc[ss]) printf("TAK\n"); else printf("NIE\n");
}
}
return 0;
}