BZOJ4068 : [Ctsc2015]app

Claris發表於2016-01-30

對於一個所選任務集合,如果對於任意時刻$i$,$i$前面所選任務數都不超過i的話,那麼這些任務可以全選。

維護一棵線段樹$T$,第$i$個位置一開始為$i$,每使用一個任務,$[t,T]$都要減$1$。

 

插入一個任務:

首先查詢$[t,T]$的區間內第一個$0$的位置,記為$k$。

如果沒有$0$,那麼可以直接加入這個任務。

否則要麼不用這個任務,要麼拿這個任務去替換$t$在$[1,k]$裡價值最小的任務。

 

刪除一個任務:

如果沒有使用,那麼直接刪除。

否則$[t,T]$都要加$1$,然後找到最後一個$0$的位置$k$。

那麼要在備用任務集合中取出$t$在$[k+1,T]$裡價值最大的任務,加入答案。

 

於是再按$t$用兩棵線段樹分別維護兩個集合即可。

時間複雜度$O(Q\log T)$。

 

#include<cstdio>
#include<set>
#include<map>
#include<algorithm>
using namespace std;
typedef pair<int,int>P;
const int N=300010,M=1050000;
int n,m,x,y,z,g[N],nxt[N],ed,cnt;char ch;long long ans;map<P,int>id;
struct E{int t,p,u;E(){}E(int _t,int _p){t=_t,p=_p,u=0;}}e[N];
inline int getid(int x,int y){
  int t=id[P(x,y)],p=g[t];
  g[t]=nxt[g[t]];
  return p;
}
inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
int v[M],tag[M];
inline void add1(int x,int p){v[x]+=p,tag[x]+=p;}
inline void pb(int x){if(tag[x])add1(x<<1,tag[x]),add1(x<<1|1,tag[x]),tag[x]=0;}
inline void up(int x){v[x]=min(v[x<<1],v[x<<1|1]);}
void build(int x,int a,int b){
  v[x]=a;
  if(a==b)return;
  int mid=(a+b)>>1;
  build(x<<1,a,mid),build(x<<1|1,mid+1,b);
}
void add(int x,int a,int b,int c,int d,int p){
  if(c<=a&&b<=d){add1(x,p);return;}
  pb(x);
  int mid=(a+b)>>1;
  if(c<=mid)add(x<<1,a,mid,c,d,p);
  if(d>mid)add(x<<1|1,mid+1,b,c,d,p);
  up(x);
}
int left(int x,int a,int b,int c,int d){
  if(v[x])return 0;
  if(a==b)return a;
  pb(x);
  int mid=(a+b)>>1,t=0;
  if(c<=mid)t=left(x<<1,a,mid,c,d);
  if(!t&&d>mid)t=left(x<<1|1,mid+1,b,c,d);
  up(x);
  return t;
}
int right(int x,int a,int b,int c,int d){
  if(v[x])return 0;
  if(a==b)return a;
  pb(x);
  int mid=(a+b)>>1,t=0;
  if(d>mid)t=right(x<<1|1,mid+1,b,c,d);
  if(!t&&c<=mid)t=right(x<<1,a,mid,c,d);
  up(x);
  return t;
}
struct SegmentTree{
set<P>A[N];int cnt[N],mi[M],ma[M];
inline int umax(int a,int b){
  if(!a)return b;
  if(!b)return a;
  return e[a].p>e[b].p?a:b;
}
inline int umin(int a,int b){
  if(!a)return b;
  if(!b)return a;
  return e[a].p<e[b].p?a:b;
}
void add(int x,int a,int b,int c,int p){
  if(a==b){
    cnt[a]++;
    A[a].insert(P(e[p].p,p));
    mi[x]=A[a].begin()->second;
    ma[x]=A[a].rbegin()->second;
    return;
  }
  int mid=(a+b)>>1;
  if(c<=mid)add(x<<1,a,mid,c,p);else add(x<<1|1,mid+1,b,c,p);
  mi[x]=umin(mi[x<<1],mi[x<<1|1]);
  ma[x]=umax(ma[x<<1],ma[x<<1|1]);
}
void del(int x,int a,int b,int c,int p){
  if(a==b){
    cnt[a]--;
    A[a].erase(P(e[p].p,p));
    if(cnt[a]){
      mi[x]=A[a].begin()->second;
      ma[x]=A[a].rbegin()->second;
    }else mi[x]=ma[x]=0;
    return;
  }
  int mid=(a+b)>>1;
  if(c<=mid)del(x<<1,a,mid,c,p);else del(x<<1|1,mid+1,b,c,p);
  mi[x]=umin(mi[x<<1],mi[x<<1|1]);
  ma[x]=umax(ma[x<<1],ma[x<<1|1]);
}
int askmin(int x,int a,int b,int c,int d){
  if(c<=a&&b<=d)return mi[x];
  int mid=(a+b)>>1,t=0;
  if(c<=mid)t=askmin(x<<1,a,mid,c,d);
  if(d>mid)t=umin(t,askmin(x<<1|1,mid+1,b,c,d));
  return t;
}
int askmax(int x,int a,int b,int c,int d){
  if(c<=a&&b<=d)return ma[x];
  int mid=(a+b)>>1,t=0;
  if(c<=mid)t=askmax(x<<1,a,mid,c,d);
  if(d>mid)t=umax(t,askmax(x<<1|1,mid+1,b,c,d));
  return t;
}
}T1,T2;
inline void addtask(int x){
  int t=e[x].t,k=left(1,1,n,t,n);
  if(!k){
    add(1,1,n,t,n,-1);
    T1.add(1,1,n,t,x);
    e[x].u=1;
    ans+=e[x].p;
  }else{
    int y=T1.askmin(1,1,n,1,k);
    if(e[y].p<e[x].p){
      add(1,1,n,e[y].t,n,1);
      T1.del(1,1,n,e[y].t,y);
      T2.add(1,1,n,e[y].t,y);
      e[y].u=0;
      add(1,1,n,t,n,-1);
      T1.add(1,1,n,t,x);
      e[x].u=1;
      ans+=e[x].p-e[y].p;
    }else T2.add(1,1,n,t,x);
  }
}
inline void deltask(int x){
  if(!e[x].u)T2.del(1,1,n,e[x].t,x);
  else{
    ans-=e[x].p;
    add(1,1,n,e[x].t,n,1);
    T1.del(1,1,n,e[x].t,x);
    int k=right(1,1,n,1,n),y=T2.askmax(1,1,n,k+1,n);
    if(y){
      add(1,1,n,e[y].t,n,-1);
      T2.del(1,1,n,e[y].t,y);
      T1.add(1,1,n,e[y].t,y);
      e[y].u=1;
      ans+=e[y].p;
    }
  }
}
int main(){
  read(n),read(m),build(1,1,n);
  while(m--){
    while((ch=getchar())!='A'&&ch!='D');
    read(x),read(y);
    if(ch=='A'){
      e[++ed]=E(x,y);
      if(!id[P(x,y)])z=id[P(x,y)]=++cnt;else z=id[P(x,y)];
      nxt[ed]=g[z],g[z]=ed;
      addtask(ed);
    }else deltask(getid(x,y));
    printf("%lld\n",ans);
  }
  return 0;
}

  

相關文章