• 【题解】康拓展开(养生题)


    【题解】康拓展开(养生题)

    养生养生

    编号 题目 状态 分数 总时间 内存 代码 / 答案文件 提交者 提交时间
    #528662 #167. 康托展开 Accepted 100 1129 ms 8060 K C++ 11 (Clang) / 1.2 K winlere 2019-07-17 8:29:28

    假如说我的排列是这样的

    [2 quad3 quad4quad5quad1 ]

    可以从左往右扫,扫到第一个时,发现这个位置不是(1),而是(2),说明至少经历了((2-1) imes (5-1)!)次排列才可能第一个是(2)。把第一个判断完之后,就剩下了一个子排列,是个子问题。不过要动态维护每个数在当前剩下的数的排名,开个值域线段树就好了。

    //@winlere
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    
    
    using namespace std;  typedef long long ll;
    inline int qr(){
          register int ret=0,f=0;
          register char c=getchar();
          while(c<48||c>57)f|=c==45,c=getchar();
          while(c>=48&&c<=57) ret=ret*10+c-48,c=getchar();
          return f?-ret:ret;
    }
    const int mod=998244353;
    const int maxn=1e6+5;
    int jc[maxn],n;
    int data[maxn];
    #define lowbit(x) ((x)&(-(x)))
    inline void add(const int&pos,const int&ad){
          for(register int t=pos;t<=n;t+=lowbit(t))
    	    data[t]=data[t]+ad;
    }
    
    inline int q(const int&pos){
          register ll ret=0;
          for(register int t=pos;t;t-=lowbit(t))
    	    ret+=data[t];
          return ret;
    }
    
    inline void add(const int&l,const int&r,const int&ad){
          if(l>r)return;
          add(l,ad);add(r+1,-ad);
    }
    
    
    int main(){
          int ans=1;
          n=qr();
          jc[0]=1;
          for(register int t=1;t<=n;++t)
    	    jc[t]=1ll*jc[t-1]*t%mod;
          for(register int t=1;t<=n;++t)
    	    add(t,t,t);
          for(register int t=1,t1;t<=n;++t){
    	    t1=qr();
    	    ans=(ans+1ll*(q(t1)-1)*jc[(n-t)]%mod)%mod;
    	    add(t1+1,n,-1);
          }
          printf("%d
    ",ans);
          return 0;
    }
    
    
  • 相关阅读:
    带有时间间隔的dp
    单调队列优化dp(捡垃圾的机器人)
    实现技巧
    树形dp(灯与街道)
    括号匹配(数组链表模拟)
    二分,求直线上覆盖所有点的最短时间
    可持久化链表(链式前向星)
    二分图匹配模板题
    网络流,设备、插头和转接器建图(简单map的应用)
    第七周助教总结
  • 原文地址:https://www.cnblogs.com/winlere/p/11198706.html
Copyright © 2020-2023  润新知