• 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;
    }
    

      

  • 相关阅读:
    asp.net 通过js调用webService注意
    身份证号码验证 类
    char值码对应大全
    C# 让textbox 只能输入数字的方法
    table嵌套循环数据
    拆分字符串
    angular的路由配置
    js对象数组(JSON) 根据某个共同字段 分组
    当前时间的后七天
    ajax提交时“加载中”提示的处理方法
  • 原文地址:https://www.cnblogs.com/clrs97/p/5170412.html
Copyright © 2020-2023  润新知