zoukankan      html  css  js  c++  java
  • AGC001 F

    给出的模型很难搞,所以转换一下,记p[i]为i这个数的位置,然后相邻两个p值差>k的能交换,发现使原问题字典序最小也需要使这里的字典序最小
    注意到p值差<=k的前后顺序一定不変,那么可以n^2建图用堆跑最小字典序拓扑序
    考虑优化,每个点需要向[p[i]-k+1,p[i]+k-1]这段区间的数连边,但是有一些边是多余的,也就是区间[p[i]-k+1,p[i]],[p[i],p[i]+k-1]这两个区间内的数一定两两有边所以连向当前点后面最近的一个即可,这个用线段树来找

    #include<iostream>
    #include<cstdio>
    #include<queue>
    using namespace std;
    const int N=3000005;
    int n,k,a[N],p[N],h[N],cnt,d[N],tot;
    struct xds
    {
    	int l,r,p;
    }t[N];
    struct qwe
    {
    	int ne,to;
    }e[N];
    int read()
    {
    	int r=0,f=1;
    	char p=getchar();
    	while(p>'9'||p<'0')
    	{
    		if(p=='-')
    			f=-1;
    		p=getchar();
    	}
    	while(p>='0'&&p<='9')
    	{
    		r=r*10+p-48;
    		p=getchar();
    	}
    	return r*f;
    }
    void build(int ro,int l,int r)
    {
    	t[ro].l=l,t[ro].r=r,t[ro].p=n+1;
    	if(l==r)
    		return;
    	int mid=(l+r)>>1;
    	build(ro<<1,l,mid);
    	build(ro<<1|1,mid+1,r);
    }
    void update(int ro,int p,int v)
    {
    	if(t[ro].l==t[ro].r)
    	{
    		t[ro].p=v;
    		return;
    	}
    	int mid=(t[ro].l+t[ro].r)>>1;
    	if(p<=mid)
    		update(ro<<1,p,v);
    	else
    		update(ro<<1|1,p,v);
    	t[ro].p=min(t[ro<<1].p,t[ro<<1|1].p);
    }
    int ques(int ro,int l,int r)
    {
    	if(t[ro].l==l&&t[ro].r==r)
    		return t[ro].p;
    	int mid=(t[ro].l+t[ro].r)>>1;
    	if(r<=mid)
    		return ques(ro<<1,l,r);
    	else if(l>mid)
    		return ques(ro<<1|1,l,r);
    	else
    		return min(ques(ro<<1,l,mid),ques(ro<<1|1,mid+1,r));
    }
    void add(int u,int v)
    {//cerr<<u<<" "<<v<<endl;
    	cnt++;
    	e[cnt].ne=h[u];
    	e[cnt].to=v;
    	d[v]++;
    	h[u]=cnt;
    }
    int main()
    {
    	n=read(),k=read();
    	for(int i=1;i<=n;i++)
    		a[i]=read(),p[a[i]]=i;
    	build(1,1,n);
    	for(int i=n;i>=1;i--)
    	{
    		int x=ques(1,p[i],min(n,p[i]+k-1)),y=ques(1,max(1,p[i]-k+1),p[i]);
    		if(x<=n)
    			add(p[i],p[x]);
    		if(y<=n)
    			add(p[i],p[y]);
    		update(1,p[i],i);
    	}
    	priority_queue<int,vector<int>,greater<int> >q;
    	for(int i=1;i<=n;i++)
    		if(!d[i])
    			q.push(i);
    	while(!q.empty())
    	{
    		int u=q.top();
    		p[++tot]=u;
    		q.pop();
    		for(int i=h[u];i;i=e[i].ne)
    			if(!(--d[e[i].to]))
    				q.push(e[i].to);
    	}
    	for(int i=1;i<=n;i++)
    		a[p[i]]=i;
    	for(int i=1;i<=n;i++)
    		printf("%d
    ",a[i]);
    	return 0;
    }
    
  • 相关阅读:
    我的省选 Day -9
    我的省选 Day -10
    我的省选 Day -11
    我的省选 Day -12
    我的省选 Day -13
    [NOI2013]快餐店
    我的省选 Day -14
    杭电多校2020第7场-E Expectation
    「联合省选2020」组合数问题
    UR#19 通用评测号
  • 原文地址:https://www.cnblogs.com/lokiii/p/10928043.html
Copyright © 2011-2022 走看看