本文主要是介绍[CF1558D]Top-Notch Insertions,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
Top-Notch Insertions
题解
首先,原操作相当于一种排序的方式,每次操作相当于告诉我们这个数比现在已经操作过且在它后面的数小,不小于它前面的数。
我们可以理解成加一个 < < <或 ⩽ \leqslant ⩽的符号。
如果我们将 i i i插入到 a j − 1 a_{j-1} aj−1与 a j a_{j} aj之间,相当于将原来两者的关系变为 a j − 1 ⩽ i < a j a_{j-1}\leqslant i<a_{j} aj−1⩽i<aj。
很容易发现,上面的操作我们可以用平衡树进行维护,注意 ∑ m ⩽ 2 × 1 0 5 \sum m\leqslant 2\times 10^5 ∑m⩽2×105但 ∑ n \sum n ∑n不保证范围,所以我们只能将它给出的操作插入到平衡树中。
既然我们可以统计出 < < <的的个数,那么我们也知道至少有多少个不同的数,我们可以枚举相同的连续 ⩽ \leqslant ⩽段与总共的不同的数的个数。
但这样仍然会使得我们的复杂度中存在 O ( ∑ n ) O\left(\sum n\right) O(∑n)因为这样差不多是从 m m m到 n n n枚举了,如果我们要让它从 0 0 0到 m m m的话就只能容斥了。
但实际上我们有一种更加简便的做法。
如果全都是 ⩽ \leqslant ⩽的话我们的方案数是 ( 2 n n ) \binom{2n}{n} (n2n),相当于就是差分的形式,选择的点前面有多少个点没有选择,就是它的值。
如果加入 < < <我们可以看作每个 < < <自己绑定一个没选的空点,与上面一样,方案数为 ( 2 n − t n ) \binom{2n-t}{n} (n2n−t), t t t表示有多少个 < < <。
时间复杂度 O ( ∑ m l o g m ) O\left(\sum mlog\,m\right) O(∑mlogm)
源码
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
#define MAXN 400005
#define lowbit(x) (x&-x)
#define reg register
#define pb push_back
#define mkpr make_pair
#define lson (rt<<1)
#define rson (rt<<1|1)
#define fir first
#define sec second
typedef long long LL;
typedef unsigned long long uLL;
const LL INF=0x3f3f3f3f3f3f;
const int mo=998244353;
const int inv2=499122177;
const int jzm=2333;
const int zero=10000;
const int lim=10000;
const int orG=3,invG=332748118;
const double Pi=acos(-1.0);
const double eps=1e-7;
typedef pair<int,int> pii;
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){_T f=1;x=0;char s=getchar();while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}x*=f;
}
template<typename _T>
void print(_T x){if(x<0){x=(~x)+1;putchar('-');}if(x>9)print(x/10);putchar(x%10+'0');}
LL gcd(LL a,LL b){return !b?a:gcd(b,a%b);}
int add(int x,int y,int p){return x+y<p?x+y:x+y-p;}
void Add(int &x,int y,int p){x=add(x,y,p);}
int qkpow(int a,int s,int p){int t=1;while(s){if(s&1LL)t=1ll*a*t%p;a=1ll*a*a%p;s>>=1LL;}return t;}
int n,m,p[MAXN];
int ans,fac[MAXN],inv[MAXN],f[MAXN];
void init(){fac[0]=fac[1]=inv[0]=inv[1]=f[1]=1;for(int i=2;i<=4e5;i++)fac[i]=1ll*i*fac[i-1]%mo,f[i]=1ll*(mo-mo/i)*f[mo%i]%mo,inv[i]=1ll*f[i]*inv[i-1]%mo;
}
int C(int x,int y){if(x<0||y<0||x<y)return 0;return 1ll*fac[x]*inv[y]%mo*inv[x-y]%mo;
}
struct ming{int siz,rnd,val,ch[2],sum,lzy,id;ming(){siz=rnd=val=sum=ch[0]=ch[1]=lzy=0;}
};
class FHQ_Treap{private:ming tr[MAXN];int tot,root;int newnode(int x,int y){int rt=++tot;tr[rt].siz=1;tr[rt].rnd=rand();tr[rt].ch[0]=tr[rt].ch[1]=tr[rt].lzy=0;tr[rt].val=tr[rt].sum=x;tr[rt].id=y;return rt; }void pushdown(int rt){if(tr[rt].lzy){if(tr[rt].ch[0])tr[tr[rt].ch[0]].lzy+=tr[rt].lzy,tr[tr[rt].ch[0]].id+=tr[rt].lzy;if(tr[rt].ch[1])tr[tr[rt].ch[1]].lzy+=tr[rt].lzy,tr[tr[rt].ch[1]].id+=tr[rt].lzy;tr[rt].lzy=0;}}void pushup(int rt){tr[rt].siz=1+tr[tr[rt].ch[0]].siz+tr[tr[rt].ch[1]].siz;tr[rt].sum=tr[rt].val+tr[tr[rt].ch[0]].sum+tr[tr[rt].ch[1]].sum;}void split(int now,int k,int &x,int &y){if(!now){x=y=0;return ;}pushdown(now);if(k==tr[now].id){y=tr[now].ch[1],tr[now].ch[1]=0,x=now;pushup(x);return ; }if(k>=tr[now].id)x=now,split(tr[now].ch[1],k,tr[x].ch[1],y),pushup(x);else y=now,split(tr[now].ch[0],k,x,tr[y].ch[0]),pushup(y);}int merge(int a,int b){if(!a||!b)return a+b;pushdown(a);pushdown(b);if(tr[a].rnd<tr[b].rnd){tr[a].ch[1]=merge(tr[a].ch[1],b);pushup(a);return a;}tr[b].ch[0]=merge(a,tr[b].ch[0]);pushup(b);return b;}public:void insert(int ip,int k){int x1,y1,x2,y2;split(root,k-1,x1,y1);split(x1,k-2,x2,y2);if(y1)tr[y1].lzy++,tr[y1].id++;if(y2)tr[y2].val=tr[y2].sum=0;root=merge(merge(x2,y2),merge(newnode(ip!=k,k),y1));}int query(){return tr[root].sum;}void clear(){for(int i=1;i<=tot;i++)tr[i].ch[0]=tr[i].ch[1]=tr[i].val=tr[i].rnd=tr[i].siz=tr[i].lzy=tr[i].id=0;root=tot=0;}
}T;
signed main(){int tt;read(tt);init();while(tt--){read(n);read(m);ans=0;for(int i=1,x,y;i<=m;i++)read(x),read(y),T.insert(x,y);//,T.Search();int t=T.query();printf("%d\n",C(n+n-t-1,n));T.clear();}return 0;
}
谢谢!!!
这篇关于[CF1558D]Top-Notch Insertions的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!