• 康托展开


    洛谷日报187浅谈康托展开

    树状数组版本。

    完整版

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    ll n,m,a[100009],fac[10009];
    bool vis[100009];
    ll tree[100009];
    ll lowbit(int x){return x&(-x);}
    void add(ll x,ll w){
       while(x<=n){
       	tree[x]+=w;
       	x+=lowbit(x);
       }
    }
    ll ask(ll x){
       ll ans=0;
       while(x>0){
       	ans+=tree[x];
       	x-=lowbit(x);
       }
       return ans;
    }
    void kangtuo()
    {
       ll ans=0;
       for(int i=1;i<=n;i++)	add(i,1);
       for(int i=1;i<=n;i++)
       {
       	scanf("%lld",&a[i]);
       	add(a[i],-1);//划掉这个数 
       	ans+=ask(a[i])*fac[n-i];//找前面有几个比自己小的数 
       }
       cout<<ans+1<<endl;
    }
    void nikangtuo()
    {
       memset(vis,0,sizeof(vis));
       ll rank;
       cin>>rank;rank--;
       for(ll i=1;i<=n;i++)
       {
       	ll temp=rank/fac[n-i];//把过程逆转回去,找第temp大的 
       	for(ll j=1;j<=n;j++)
       	{
       		if(vis[j])	continue;
       		if(temp==0)
       		{
       			cout<<j<<" ";
       			vis[j]=1;
       			break;
       		}
       		temp--;
       	}
       	rank%=fac[n-i];
       }
       cout<<endl;
    }
    int main()
    {
       char s;
       cin>>n>>m;
       fac[0]=1;
       for(int i=1;i<=n;i++)	fac[i]=fac[i-1]*i;
       for(int i=1;i<=m;i++)
       {
       	cin>>s;
       	if(s=='P')	nikangtuo();
       	else		kangtuo();
       }
    }
    
    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int mod=998244353;
    int tree[1000009],a[1000009],n;
    int lowbit(int x){
    	return x&(-x);
    }
    int ask(int x){
    	int ans=0;
    	while(x>0){
    		ans+=tree[x];
    		x-=lowbit(x);
    	}
    	return ans;
    }
    void add(int x,int k){
    	while(x<=n){
    		tree[x]+=k;
    		x+=lowbit(x);
    	}
    }
    int main()
    {
    	cin>>n;
    	for(int i=1;i<=n;i++)
    	{
    		scanf("%d",&a[i]);
    		int x=a[i]-ask(a[i]);
    		add(a[i],1);
    		a[i]=x-1;
    	}
    	ll ans=0;
    	for(int i=1;i<n;i++)
    		ans=(ans+a[i])*(n-i)%mod;
    	cout<<(ans+1)%mod;
    }
    

    逆康托展开(还看不懂)

    
    LL Check(LL l,LL r,LL aim) {
    	while(l < r) {
    		LL mid = (l + r) >> 1;
    		if(query(mid) - 1 >= aim) {
    			r = mid;
    		} else {
    			l = mid + 1;
    		}
    	}
    	return r;
    }
    
    void reCantor() {
    	pos --;   // 需要先 -- (排名从 0 开始)
    	for(LL i = 1,num = n - 1; i <= n; num --, i ++) {
    		LL aim = pos / fac[num];                     // 找 第 k 大的数 
    		pos = pos % fac[num];
    		LL t = Check(1,n,aim);
    		cout << t << " ";
    		add(t ,-1);                 // 与上面的解释一样
    	}
    	cout << endl;
    	return ;
    }
    
    
  • 相关阅读:
    正向代理与反向代理的区别
    php返回数据格式化类
    RewriteCond和13个mod_rewrite应用举例Apache伪静态
    sh cssupdate
    JS小游戏仙剑翻牌
    sh cssupdate 优化
    Apache rewrite
    php XML文件解释类
    memcached 常用命令及使用说明
    Apache 搭建虚拟主机
  • 原文地址:https://www.cnblogs.com/iss-ue/p/12682269.html
Copyright © 2020-2023  润新知