思路
显然,he >= (c - k) * s 时,输出 TAK,否则 NIE
c 和 s 的含义如题目
he 的含义:小于 s 的数 的和
k 的含义:大于等于 s 的数 的数目
问题转化为 快速求 he 和 k:使用树状数组
显然 我们先需要离散化:将 m 个询问里的 a 和 s 进行离散化
然后 维护两个树状数组:
对于 k :我们可以维护一个树状数组 tr
add(tr,x,v) 表示:让数字 x ,其数目 + v
sum(tr,x) 表示:大小在 [1,x] 区间内 的数字的数目
对于 he:我们可以维护一个树状数组 trr
add(trr,x,v) 表示:让位置 x 上 的和 + v
sum(trr,x) 表示:所有 在 [1,x] 区间内 的位置,其上面和 的 总和
ps:离散化后,记得记录 a 和 s 离散化前的原值 即 val[ ],会用到
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6+10;
vector<int> v;
int a[N],val[N];
ll tr[N],trr[N];
int n,m;
struct node{
char op;
int x,y;
}p[N];
int lowbit(int x){
return x & -x;
}
void add(ll t[],ll x,ll v){
for(int i=x;i<=N;i+=lowbit(i)) t[i]+=v; // 注意是 N,而不是 n
}
ll sum(ll t[],ll x){
ll res=0;
for(int i=x;i;i-=lowbit(i)) res+=t[i];
return res;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
char op[2];
int x,y;
scanf("%s%d%d",op,&x,&y);
p[i]={op[0],x,y};
v.push_back(y);
}
sort(v.begin(),v.end());
v.erase(unique(v.begin(),v.end()),v.end());
for(int i=1;i<=m;i++){
p[i].y=lower_bound(v.begin(),v.end(),p[i].y)-v.begin()+1;
val[p[i].y]=v[p[i].y-1];
}
for(int i=1;i<=m;i++){
char op=p[i].op;
int x=p[i].x,y=p[i].y;
if(op=='U'){
if(a[x]!=0) add(tr,a[x],-1),add(trr,a[x],-val[a[x]]); // 树状数组的下标 必须 >=1
add(tr,y,1),add(trr,y,val[y]);
a[x]=y;
}
else{
int k=sum(tr,N)-sum(tr,y-1); // 注意是 N,而不是 n
ll he=sum(trr,y-1);
if(he>=(ll)(x-k)*val[y]) puts("TAK");
else puts("NIE");
}
}
return 0;
}