• ZYB's Premutation(树状数组+二分)


     

     

    分析:我们可以逆向考虑(因为正向的话由于第一位的逆序对数一定是0,算不出什么),对于第i个数,它使逆序对的数量增加了temp=num[i]-num[i-1],即区间【1,i-1】内比这个数大的有temp个,即它在i个数中从小到大排在(i-temp)个,那么找到这个数即可。

    对于答案序列来讲,他是一个全排列的一种情况,对于用过了的数肯定就不再使用了。那么接下来的任务就是在剩余的数中,挑取第i-(num【i】-num【i-1】)大的数,作为这个位子上的答案;

    那么这部分我们可以用树状数组+二分来完成任务。

    对于树状数组,我们初始化每个位子上的val都是1.表示每个数字都还没被用过。那么getsum(i)的操作,就是在查找【1,i】这些数字中还剩余多少个数。

    那么我们考虑二分这个最终位子pos,使得【1,pos】中剩余的数字为i-(num【i】- num【i-1】)个即可。

    那么很容易理解,ans【i】=pos;

    对应每一次找到一个答案之后,对应updata(pos,-1)归零即可,表示这个位子上的这个数字我们已经用过了。

    AC_Code:

     1 #include <iostream>
     2 #include <string>
     3 #include <cstring>
     4 #include <cstdio>
     5 #include <algorithm>
     6 using namespace std;
     7 typedef long long ll;
     8 #define lowbit(x) ((x)&(-x))
     9 #define rep(i,first,last) for(int i=first;i<=last;i++)
    10 #define dep(i,first,last) for(int i=first;i>=last;i--)
    11 const int maxn=5e4+10;
    12 const int inf=0x3f3f3f3f;
    13 
    14 int num[maxn],tree[maxn],ans[maxn],n;
    15 
    16 void updata(int i,int k){
    17     while( i<=n ){
    18         tree[i]+=k;
    19         i+=lowbit(i);
    20     }
    21 }
    22 
    23 int getsum(int i){
    24     int res=0;
    25     while( i>0 ){
    26         res+=tree[i];
    27         i-=lowbit(i);
    28     }
    29     return res;
    30 }
    31 
    32 int solve(int k){
    33     int ans=0;
    34     int l=1;
    35     int r=n;
    36     while( l<=r ){
    37         int mid=(l+r)>>1;
    38         if( getsum(mid)>=k ){
    39             ans=mid;
    40             r=mid-1;
    41         }
    42         else l=mid+1;
    43     }
    44     return ans;
    45 }
    46 
    47 int main()
    48 {
    49     int T;
    50     scanf("%d",&T);
    51     while( T-- ){
    52         memset(tree,0,sizeof(tree));
    53         scanf("%d",&n);
    54         rep(i,1,n){
    55             updata(i,1);
    56             scanf("%d",&num[i]);
    57         }
    58         dep(i,n,1){
    59             int temp=num[i]-num[i-1];
    60             temp=i-temp;
    61             ans[i]=solve(temp);
    62             updata(ans[i],-1);
    63         }
    64         rep(i,1,n-1){
    65             printf("%d ",ans[i]);
    66         }
    67         printf("%d
    ",ans[n]);
    68     }
    69     return 0;
    70 }
  • 相关阅读:
    python3与Excel的完美结合
    Python3连接MySQL
    Jmeter用BeanShell Sampler调用java写的jar包进行MD5加密
    Jmeter 接口测试之MD5加密函数(函数助手篇)
    ubuntu16.04安装python3
    解释Crypto模块怎么就这么"皮"?No module named "Crypto"
    python3 django 安装
    未授权访问的缺陷原理的一种可能性
    一篇RPO漏洞挖掘文章翻译加深理解。
    漏洞挖掘技巧之利用javascript:
  • 原文地址:https://www.cnblogs.com/wsy107316/p/12324389.html
Copyright © 2020-2023  润新知