CF1443E Long Permutation(暴力)
题目描述
维护长为 \(n\) 的排列 \(P\),有以下两种操作:
1 l r,输出 \(\displaystyle\sum_{i=l}^{r}P_i\)。2 x,将 \(P\) 替换成 \(P\) 的下 \(x\) 个排列。
排列 \(P\) 初始为 \([1,2,\cdots,n]\),一共有 \(q\) 次操作。
数据范围:\(2\leq n\leq 2\times 10^5,1\leq q\le 2\times 10^5,1\leq x\leq 10^5\)。
分析
假设 \(q=10^5\),\(x=10^5\),则最大的排列也不会超过 \(10^{10}\),而 \(15!\approx130\times 10^{10}>10^{10}\),即最多最后 \(15\) 位会发生改变,前面的数都不会变。维护前缀和,修改的时候暴力修改最后几位即可。
代码
#include <bits/stdc++.h>
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;
}
int vis[200010];
long long fac[100],sum[200010];
void init()
{
fac[0]=1;
for(int i=1;i<=20;i++)
fac[i]=fac[i-1]*i;
}
int main()
{
init();
int n,q;
cin>>n>>q;
int pos=max(1,n-15);
for(int i=1;i<=n;i++)
sum[i]=sum[i-1]+i;
long long cnt=1;
while(q--)
{
int op=read();
if(op==1)
{
int l=read(),r=read();
printf("%lld\n",sum[r]-sum[l-1]);
}
else
{
int x=read();
cnt=cnt+x;
long long temp=cnt;
for(int i=pos;i<=n;i++)
vis[i]=0;
for(int i=pos;i<=n-1;i++)
{
long long res=0;
for(int j=pos;j<=n;j++)
{
if(vis[j]==0)
{
res=res+fac[n-i];
if(res>=temp)
{
temp=temp-(res-fac[n-i]);
sum[i]=sum[i-1]+j;
vis[j]=1;
break;
}
}
}
}
for(int i=pos;i<=n;i++)
if(vis[i]==0)
sum[n]=sum[n-1]+i;
}
}
return 0;
}
posted on 2020-11-04 12:01 DestinHistoire 阅读(111) 评论(0) 收藏 举报
浙公网安备 33010602011771号