zoukankan      html  css  js  c++  java
  • CF732D

    今上午的模拟赛考了这道题,改了一下题面。

    本来切掉了,考场源码交到 CF 上也过了,但是因为你教师机评测太牛逼硬是把我代码判错了,现在也不是很理解为什么。


    用了一种和大多数人不一样的方法。

    首先考虑什么时候无解。

    显然,越晚攻击一个敌人,就越有可能击败他。也就是说,如果我们让所有敌人在最后出现时刻时被攻击,仍不能击败所有人,那么无解。

    然后我们再考虑如何取最优答案。

    让所有人在最后时刻被击败肯定是最劣的一种答案,那么想要使答案尽可能优,肯定要每次找出最后一个被消灭的敌人,使他的出现时刻变成上一个,再尝试能否全部击败。

    接着考虑一下,移动一个敌人会产生什么影响。

    我们先记录最劣情况下到每个时刻的士兵数量。

    假设我们最后出现的敌人位置为 (x),这个敌人的上一个出现位置是 (y),消灭这个敌人需要花费 (v) 的士兵。

    那么我们把这个士兵从 (x) 移走,显然 ([x,n]) 位置的士兵数要在现在的基础上加 (v+1) 个(攻击花费的 (v) 个与走到 (x) 位置时新增的 (1) 个)。

    然后我们把这个士兵插入到位置 (y),那么 ([y,n]) 的士兵数要在现在的基础上减去 (v+1) 个,理由同上。

    如何判断移动这个士兵合不合法呢?只需要判断减去这个值之后,([y,n]) 位置有没有出现负数即可,原因显然。具体操作时可以求出 ([y,n]) 位置的最小值,判断一下是否大于等于 (v+1)

    所以我们只需要对序列进行区间加和区间求最小值两种操作,上线段树即可。

    bool vis[maxn];
    int n,m,tot,Ans,all,a[maxn];
    int lst[maxn],ck[maxn];
    int pos[maxn],val[maxn];
    deque<int> id[maxn];
    struct node{int a,b;};
    deque<node> q;
    
    namespace Seg{
      #define ls x<<1
      #define rs x<<1|1
      int minx[maxn<<2],lazy[maxn<<2];
      
      void pushup(int x){
        minx[x]=min(minx[ls],minx[rs]);
      }
      
      void pushdown(int x){
        if(lazy[x]==0) return;
        lazy[ls]+=lazy[x];lazy[rs]+=lazy[x];
        minx[ls]+=lazy[x];minx[rs]+=lazy[x];
        lazy[x]=0;
      }
      
      void build(int x,int l,int r){
        if(l==r){
          minx[x]=a[l];
          return;
        }
        int mid=l+r>>1;
        build(ls,l,mid);
        build(rs,mid+1,r);
        pushup(x);
      }
      
      void update1(int x,int l,int r,int L,int R,int val){
        if(L<=l&&R>=r){
          minx[x]+=val;
          lazy[x]+=val;
          return;
        }
        int mid=l+r>>1;pushdown(x);
        if(L<=mid) update1(ls,l,mid,L,R,val);
        if(R>=mid+1) update1(rs,mid+1,r,L,R,val);
        pushup(x);
      }
      
      int query(int x,int l,int r,int L,int R){
        if(L<=l&&R>=r) return minx[x];
        int mid=l+r>>1,ans=INF;pushdown(x);
        if(L<=mid) ans=min(ans,query(ls,l,mid,L,R));
        if(R>=mid+1) ans=min(ans,query(rs,mid+1,r,L,R));
        return ans;
      }
    }
    
    signed main(){
      n=read(); m=read();
      for(int i=1;i<=n;i++){
        pos[i]=read();
        if(pos[i]){
          id[pos[i]].push_front(i);
          q.push_front((node){i,pos[i]});
        }
      }
      for(int i=n;i>=1;i--){
        if(!vis[pos[i]]||!pos[i]){
          vis[pos[i]]=1;
          if(pos[i]) lst[i]=pos[i],id[pos[i]].pop_front(),Ans=max(Ans,i);
        }
        else lst[i]=0;  
      }
      for(int i=1;i<=m;i++) val[i]=read();
      for(int i=1;i<=n;i++){
        if(lst[i]){
          all++;
          tot-=val[lst[i]];
          if(tot<0) return puts("-1"),0; 
        }
        else tot++;
        a[i]=tot;
      }
      if(all<m) return puts("-1"),0;
      Seg::build(1,1,n);
      while(1){
        if(q.size()==m) break;
        node P=q.front();q.pop_front();
        
        int fir=P.a,sec=P.b;
        int nxt_pos=id[sec].front();  
        
        id[sec].pop_front();
        Seg::update1(1,1,n,fir,n,1+val[sec]);
        int minx=Seg::query(1,1,n,nxt_pos,n);
        
        if(minx<1+val[sec]||minx>=INF) return printf("%d
    ",Ans),0;
        Seg::update1(1,1,n,nxt_pos,n,-1-val[sec]);Ans=q.front().a;
      }
      printf("%d
    ",Ans);
      return 0;
    }
    
  • 相关阅读:
    19.音乐查询l练习
    python用requests爬取新浪财经首页要闻
    关于Pyhton正则报错: sre_constants.error: nothing to repeat at position
    python中的字典
    Python flask jQuery ajax 上传文件
    python中与时间有关的对象-datetime、time、date
    python os模块之实现多层目录文件查找
    python 字符串格式化输出 %d,%s及 format函数, 数字百分化输出
    linux unbuntu 虚拟环境 安装沙盒virtualenv 、virtualenvwrapper
    python实现二分查找
  • 原文地址:https://www.cnblogs.com/KnightL/p/15480864.html
Copyright © 2011-2022 走看看