AGC001F Wide Swap
Posted cjoiershiina-mashiro
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AGC001F Wide Swap相关的知识,希望对你有一定的参考价值。
Link
首先进行一个转换,我们构造(q)使得(q_{p_i}=i),那么最小化(p)的字典序实质上就是最小化(q)的字典序。
然后题目给的限制就变成了只能交换(q_i,q_{i+1}(|q_i-q_{i+1}|le k)),等价于满足(|q_i-q_j|le k(i<j))的(q_i,q_j)的相对位置不变。
这样我们就可以(q_i
ightarrow q_j)表示(q_i)必须在(q_j)前面,然后求最小拓扑序。
直接建边是(O(n^2))的,我们可以对每个(q_i),只向(j>i)的(q_jin[q_i-k+1,q_i-1])和(q_jin[q_i+1,q_i+k-1])中最近的两个连边,显然这样连边对偏序关系是没有影响的。
具体而言可以从后往前做,用线段树维护一下就好了。
#include<queue>
#include<cstdio>
#include<cctype>
#include<vector>
#include<cstring>
#include<functional>
namespace IO
{
char ibuf[(1<<21)+1],obuf[(1<<21)+1],st[15],*iS,*iT,*oS=obuf,*oT=obuf+(1<<21);
char Get(){return (iS==iT? (iT=(iS=ibuf)+fread(ibuf,1,(1<<21)+1,stdin),(iS==iT? EOF:*iS++)):*iS++);}
void Flush(){fwrite(obuf,1,oS-obuf,stdout),oS=obuf;}
void Put(char x){*oS++=x;if(oS==oT)Flush();}
int read(){int x=0,c=Get();while(!isdigit(c))c=Get();while(isdigit(c))x=x*10+c-48,c=Get();return x;}
void write(int x){int top=0;while(x)st[++top]=(x%10)+48,x/=10;while(top)Put(st[top--]);Put('
');}
}using namespace IO;
using std::vector;
using std::priority_queue;
int min(int a,int b){return a<b? a:b;}
const int N=500007,inf=0x7f7f7f7f;
vector<int>e[N];priority_queue<int,vector<int>,std::greater<int>>Q;
int n,k,p[N],q[N],mn[N<<2],deg[N];
#define ls p<<1
#define rs p<<1|1
#define mid ((l+r)>>1)
void pushup(int p){mn[p]=min(mn[ls],mn[rs]);}
void update(int p,int l,int r,int x,int v)
{
if(r==l) return (void)(mn[p]=v);
(x<=mid? update(ls,l,mid,x,v):update(rs,mid+1,r,x,v)),pushup(p);
}
int query(int p,int l,int r,int L,int R)
{
if(r<L||R<l) return inf;
if(L<=l&&r<=R) return mn[p];
return min(query(ls,l,mid,L,R),query(rs,mid+1,r,L,R));
}
int main()
{
int n=read(),k=read(),m=0;memset(mn,0x7f,sizeof mn);
for(int i=1;i<=n;++i) q[read()]=i;
for(int i=n,j;i;--i)
{
if((j=query(1,1,n,q[i]+1,q[i]+k-1))^inf) ++deg[q[j]],e[q[i]].push_back(q[j]);
if((j=query(1,1,n,q[i]-k+1,q[i]-1))^inf) ++deg[q[j]],e[q[i]].push_back(q[j]);
update(1,1,n,q[i],i);
}
for(int i=1;i<=n;++i) if(!deg[i]) Q.push(i);
for(int u;!Q.empty();)
{
q[++m]=u=Q.top(),Q.pop();
for(int v:e[u]) if(!--deg[v]) Q.push(v);
}
for(int i=1;i<=n;++i) p[q[i]]=i;
for(int i=1;i<=n;++i) write(p[i]);
return Flush(),0;
}
以上是关于AGC001F Wide Swap的主要内容,如果未能解决你的问题,请参考以下文章
0xe7f001f0!?NDK调试过程,无故抛出SIGSEGV。
COM 组件创建实例失败,原因是出现以下错误: c001f011 (Microsoft.SqlServer.ManagedDTS)