zoukankan      html  css  js  c++  java
  • BZOJ4068 : [Ctsc2015]app

    对于一个所选任务集合,如果对于任意时刻$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(Qlog 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
    ",ans);
      }
      return 0;
    }
    

      

  • 相关阅读:
    再谈TextField
    IOS-TextField知多少
    leftBarButtonItems
    LeftBarButtonItems,定制导航栏返回按钮
    Apple Mach-O Linker (id) Error "_OBJC_CLASS...错误解决办法 Apple Mach-O Linker (id) Error "_OBJC_CLASS...错误解决办法
    Unrecognized Selector Sent to Instance问题之诱敌深入关门打狗解决办法
    UNRECOGNIZED SELECTOR SENT TO INSTANCE 问题快速定位的方法
    Present ViewController,模态详解
    UILABEL AUTOLAYOUT自动换行 版本区别
    iOS自动布局解决警告Automatic Preferred Max Layout Width is not available on iOS versions prior to 8.0
  • 原文地址:https://www.cnblogs.com/clrs97/p/5170412.html
Copyright © 2011-2022 走看看