zoukankan      html  css  js  c++  java
  • Codeforces Round #740 (Div. 2, based on VK Cup 2021

    ( ext{Bottom-Tier Reversals})

    解法

    首先可以观察得到 reverse 操作并不会改变数字所在下标的奇偶性,这可以判掉无解。

    如果我们将 (n-1,n) 排到正确的位置就不会再改变它的位置,这相当于将原问题缩减到 (n-2)。所以我们可以先考虑如何排这两个数。需要注意的是,(n-1) 在偶数位置,(n) 在奇数位置。

    不妨倒着构造。首先需要达到 "(n)(1) 位置,(n-1)(2) 位置" 的状态,由此可知肯定还存在一个 "(n)(i+1) 位置,(n-1)(i) 位置" 的状态,而这个状态可以由 "(n)(j-1) 位置,(n-1)(j) 位置" 得到,只要我们翻一个 (>j) 的位置就行了。于是不妨将 (n) 先翻到 (1),设此时 (n-1) 的位置为 (p),将 (n) 翻到 (p-1),就可以倒着构造一组解。一共需要 (5) 次。

    所以总次数是 (frac{5(n-1)}{2})

    ( ext{Top-Notch Insertions})

    题目大意

    对长度为 (n) 的序列 (a) 进行插入排序,其中每个元素都在区间 ([1,n]) 之间,元素可以相等。从小到大枚举每个位置 (i),如果有 (a_{i-1}>a_i),就找到 第一个 位置 (j) 满足 (a_i<a_j) 并把 (i) 插入到 (j) 的前面,并把其记为操作 ((i,j))

    给出长度为 (m) 的操作序列 (p),请算出有多少个序列 (a) 的插入排序的操作序列为 (p)

    多组数据,(n,sum mle 2cdot 10^5)

    解法

    对于固定的操作序列,原序列和终序列是一一对应的。问题转化为统计合法终序列的个数。

    不妨设终序列为 (b)。那么它肯定满足 (forall iin[1,n),b_ile b_{i+1})

    但事实上操作序列要求某些关系是 < 的。考虑对于固定的操作序列,终序列中每个符号的位置都是固定的!所以统计个数就转化成了一个组合问题。终序列中有 (n-1) 个符号,设有 (c)<,那么方案数可以表示成 (inom{2n-c-1}{n})。具体证明就是对于每个 (b_ile b_{i+1}),将 ([i+1,n]) 中的 (b) 全部加一。这样的好处就是所有数都互不相同,而且相对关系不会发生变化。由于初始每个元素都在区间 ([1,n]) 之间,所以此时元素的最大值就是 (n+(n-1-c))。因为排列顺序已经确定,所以只用从 ([1,2n-1-c]) 中选择 (n) 个数即可。倒推回原来的序列可以用相邻两项相差 (1)

    如何求解 (c)?我们维护一个 集合 存储有哪些数 "被插" 了,答案就是集合大小(一个数可能多次 "被插",这也是 (m) 可能不等于 (c) 的原因)。可以写一个平衡树,但实际上可以倒着维护,写一个线段树二分。具体而言,对于每个操作 ((x,y)),找到当前第 (y) 个数与第 (y+1) 个数,第 (y) 个数就是这个操作插入的数,直接在线段树上删掉它。因为操作序列的 (x) 是递增的,所以不将第 (y) 个数插回去也不会影响之前的插入。

    不过需要注意复杂度要写成 (mathcal O(mlog n))

    代码

    #include <cstdio>
    #define print(x,y) write(x),putchar(y)
    
    template <class T>
    inline T read(const T sample) {
    	T x=0; char s; bool f=0;
    	while((s=getchar())>'9' or s<'0')
    		f|=(s=='-');
    	while(s>='0' and s<='9')
    		x=(x<<1)+(x<<3)+(s^48),
    		s=getchar();
    	return f?-x:x;
    }
    
    template <class T>
    inline void write(const T x) {
    	if(x<0) {
    		putchar('-'),write(-x);
    		return;
    	}
    	if(x>9) write(x/10);
    	putchar(x%10^48);
    }
    
    #include <set>
    using namespace std;
    
    const int maxn=2e5+5,mod=998244353;
    
    int n,m,x[maxn],y[maxn],roll[maxn];
    int fac[maxn<<1],ifac[maxn<<1];
    set <int> ans;
    struct SgTree {
    	int t[maxn<<2];
    	
    	void build(int o,int l,int r) {
    		t[o]=r-l+1;
    		if(l==r) return;
    		int mid=l+r>>1;
    		build(o<<1,l,mid);
    		build(o<<1|1,mid+1,r);
    	}
    	
    	int ask(int o,int l,int r,int k) {
    		while(233) {
    			int mid=l+r>>1;
    			if(l==r) return l;
    			if(k<=t[o<<1])
    				o<<=1,r=mid;
    			else {
    				k-=t[o<<1];
    				o=o<<1|1; l=mid+1;
    			}
    		} 
    	}
    	
    	void modify(int o,int l,int r,int p,int k) {
    		if(l==r) return (void)(t[o]+=k);
    		int mid=l+r>>1;
    		if(p<=mid) modify(o<<1,l,mid,p,k);
    		else modify(o<<1|1,mid+1,r,p,k);
    		t[o]=t[o<<1]+t[o<<1|1];
    	}
    } T;
    
    int inv(int x,int y=mod-2) {
    	int r=1;
    	while(y) {
    		if(y&1) r=1ll*r*x%mod; 
    		x=1ll*x*x%mod; y>>=1;
    	}
    	return r;
    }
    
    void init() {
    	fac[0]=1;
    	for(int i=1;i<=(int)4e5;++i)
    		fac[i]=1ll*fac[i-1]*i%mod;
    	ifac[(int)4e5]=inv(fac[(int)4e5]);
    	for(int i=(int)4e5-1;i>=0;--i)
    		ifac[i]=1ll*ifac[i+1]*(i+1)%mod;
    	T.build(1,1,maxn-5);
    }
    
    int C(int n,int m) {
    	if(n<m or n<0 or m<0) return 0;
    	return 1ll*fac[n]*ifac[m]%mod*ifac[n-m]%mod;
    }
    
    int main() {
    	init();
    	for(int t=read(9);t;--t) {
    		n=read(9),m=read(9);
    		ans.clear();
    		for(int i=1;i<=m;++i)
    			x[i]=read(9),y[i]=read(9);
    		for(int i=m;i>=1;--i) {
    			int u=T.ask(1,1,maxn-5,y[i]);
    			int v=T.ask(1,1,maxn-5,y[i]+1);
    			T.modify(1,1,maxn-5,u,-1);
    			ans.insert(v);
    			roll[i]=u;
    		}
    		for(int i=1;i<=m;++i)
    			T.modify(1,1,maxn-5,roll[i],1);
    		int p=ans.size();
    		print(C(2*n-p-1,n),'
    ');
    	}
    	return 0;
    }
    
  • 相关阅读:
    object sender和EventArgs e含义
    将十进制小数转化为二进制小数的方法
    什么是类、对象、方法、属性、类的成员
    asp.net代码中尖括号和百分号的含义
    打开某个AVI文件,explorer.exe遇到问题需要关闭的解决方法
    中国娱乐学习门户负责人吴晓林讲解项目
    系统流程图与业务流程图
    如何去掉Zblog的版权信息(powered by)
    利用教育游戏丰富与深化综合实践活动课程教与学的理论与实践研究 课题
    浅析C# 中object sender与EventArgs e(转)
  • 原文地址:https://www.cnblogs.com/AWhiteWall/p/15187286.html
Copyright © 2011-2022 走看看