C88 两个树状数组 P3586 [POI2015] LOG

视频链接:C88 两个树状数组 P3586 [POI2015] LOG_哔哩哔哩_bilibili

 

 

Luogu P3586 [POI2015] LOG

// 两个树状数组 O(nlogn)
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

void read(int &x){
  x=0;char c=getchar();
  while(c<'0'||c>'9') c=getchar();
  while('0'<=c&&c<='9') x=x*10+c-'0',c=getchar();
}

#define LL long long
#define N 1000005
#define lowb(x) x&-x
int n,m;char op[N];
int c[N],s[N],b[N],p[N];
LL cnt,sum,tr1[N],tr2[N]; //tr1种类数,tr2数量和

void change(LL*s,int x,int k){ //向后修
  while(x<=m) s[x]+=k,x+=lowb(x);
}
LL query(LL*s,int x){ //向前查
  LL t=0;
  while(x) t+=s[x],x-=lowb(x);
  return t;
}
int main(){
  read(n),read(m);
  for(int i=1;i<=m;++i)
    scanf(" %c",&op[i]),read(c[i]),read(s[i]),b[i]=s[i];
  sort(b+1,b+m+1); //离散化
  for(int i=1;i<=n;++i) p[i]=m+1; //无用位置
  for(int i=1,si,k;i<=m;++i){
    if(op[i]=='U'){
      k=c[i]; //修改值的下标
      si=lower_bound(b+1,b+m+1,s[i])-b; //修改值的离散值
      change(tr1,si,1);          //加上新种类数的贡献
      change(tr1,p[k],-1);       //减去旧种类数的贡献  
      change(tr2,si,b[si]);      //加上新数量的贡献
      change(tr2,p[k],-b[p[k]]); //减去旧数量的贡献
      p[k]=si; //记录第k个数的离散值
    }
    else{
      si=lower_bound(b+1,b+m+1,s[i])-b; //高度的离散值
      cnt=query(tr1,m)-query(tr1,si-1); //>=s的种类数
      sum=query(tr2,si-1); //<s的数量和
      printf("%s\n",sum>=(c[i]-cnt)*s[i]?"TAK":"NIE");
    }
  }
}

 

posted @ 2024-01-04 21:19  董晓  阅读(151)  评论(0编辑  收藏  举报