• [IOI2008] Fish 鱼


    https://www.luogu.org/recordnew/lists?uid=56840

    题解

    首先可以发现我们对于每种颜色的鱼,长一点的能够覆盖的方案已定完全包含短一点的方案。

    所以我们可以只对每种颜色最长的鱼计算贡献。

    然后有一个(naive)的想法,我们从按照最长的鱼的长度小到大枚举每种颜色,然后算出那条最长的鱼能够包含的方案。

    这样会算重。

    那么我们还有一个(naive)的想法,我们可以在枚举的时候,只维护出比在a这种颜色前面的颜色的所有方案

    这样会算少。

    考虑在什么情况吗,没有被算到。

    对于两种颜色(a,b),我们本该在枚举a的时候枚举(a,b)这种集合,结果由于排序所以没有枚举到,但在枚举b的时候因为长度原因没有够到a。

    所以我们在枚举a的时候,当我们没有拿走能够拿走的所有a的时候可以按照上面的方法做,但是如果a的全部拿走了,我们需要把所有颜色b算出来,这些b可以拿到的颜色个数是和a一样的。

    这样的话,a的数量是now+1的,枚举到b是最多枚举到now,所以不会算重。

    我也不知道我在写啥

    代码

    #include<bits/stdc++.h>
    #define N 500009
    using namespace std;
    typedef long long ll;
    int n,k,mod,cnt[N];
    int id[N],pos[N],ct[N];
    int now[N],nxt[N];
    int mx[N],_mx[N];
    ll ans;
    inline ll rd(){
      ll x=0;char c=getchar();bool f=0;
      while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
      while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
      return f?-x:x;
    }
    inline void MOD(ll &x){x=x>=mod?x-mod:x;}
    inline bool cmp(int a,int b){return mx[a]<mx[b];}
    struct node{
      int len,co;
      inline bool operator <(const node &b)const{
        return len<b.len;
      }
    }a[N];
    struct segment{
      int tr[N<<2];
      void upd(int cnt,int l,int r,int x){
        if(l==r){tr[cnt]++;return;}
        int mid=(l+r)>>1;
        if(mid>=x)upd(cnt<<1,l,mid,x);
        else upd(cnt<<1|1,mid+1,r,x);
        tr[cnt]=1ll*tr[cnt<<1]*tr[cnt<<1|1]%mod;
      }
      void build(int cnt,int l,int r){
        tr[cnt]=1;
        if(l==r)return;
        int mid=(l+r)>>1;
        build(cnt<<1,l,mid);build(cnt<<1|1,mid+1,r);
      }
      ll query(int cnt,int l,int r,int L,int R){
        if(L>R)return 1;
        if(l>=L&&r<=R)return tr[cnt];
        int mid=(l+r)>>1;
        if(mid>=L&&mid<R)return query(cnt<<1,l,mid,L,R)*query(cnt<<1|1,mid+1,r,L,R)%mod;
        if(mid>=L)return query(cnt<<1,l,mid,L,R);
        if(mid<R)return query(cnt<<1|1,mid+1,r,L,R);
      }
      inline void init(int n){build(1,1,n);}
    }T;
    inline int efs(int num,int l,int r){
      int ans=l;
      while(l<=r){
        int mid=(l+r)>>1;
        if(_mx[mid]<num)ans=mid,l=mid+1;
        else r=mid-1;
      }
      return ans;
    }
    int main(){
      n=rd();
      k=rd();
      mod=rd();
      for(int i=1;i<=n;++i){
        a[i].len=rd();a[i].co=rd();
        mx[a[i].co]=max(mx[a[i].co],a[i].len);
      }
      sort(a+1,a+n+1);
      for(int i=1;i<=k;++i)id[i]=i;
      sort(id+1,id+k+1,cmp);
      for(int i=1;i<=k;++i)pos[id[i]]=i,_mx[i]=mx[id[i]];
      for(int i=n;i>=1;--i){
        a[i].co=pos[a[i].co];
        cnt[a[i].co]++;
        nxt[i]=now[a[i].co];
        now[a[i].co]=i;
      }
      T.init(k); 
      int p=1;
      for(int i=1;i<=n;++i){
        cnt[a[i].co]--;
        while(a[p].len*2<=a[i].len)now[a[p].co]=nxt[now[a[p].co]],T.upd(1,1,k,a[p].co),ct[a[p].co]++,p++;
        if(!cnt[a[i].co]){
          int ps=efs(a[now[a[i].co]].len*2,a[i].co,k);
          ll x=T.query(1,1,k,1,a[i].co-1);
          MOD(ans+=x*ct[a[i].co]%mod);
          MOD(ans+=x*T.query(1,1,k,a[i].co+1,ps)%mod);
        }
      }
      cout<<ans;
      return 0;
    }
    
  • 相关阅读:
    IntelliJ Idea的黑色主题+代码高亮
    @EqualsAndHashCode
    @NoArgsConstructor, @RequiredArgsConstructor, @AllArgsConstructor
    springcloud各种网址
    利用PowerDesigner连接Mysql数据库并逆向所有表关系图【两种方式】
    Java 异步实现的几种方式
    如何查看Linux操作系统版本
    Java中关于WeakReference和WeakHashMap的理解
    Java弱引用(WeakReference)的理解与使用
    Unchecked Exception 和 Checked Exception 比较
  • 原文地址:https://www.cnblogs.com/ZH-comld/p/11142943.html
Copyright © 2020-2023  润新知