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;
    }
    
  • 相关阅读:
    js中拼接字符串
    js中的fliter(),map(),forEach()方法
    美化下拉框select箭头部分(不彻底)
    offsetWidth、clientWidth、scrollWidth、scrollTop、scrollLeft等属性图示
    js事件代理(事件委托)最简单的理解
    ubuntu14.04 caffe+cuda-7.0配置
    ubuntu 中安装和删除软件总结
    C++中的容器可以同时保存各种数据类型
    string的用法
    linux查看GPU的配置和使用信息
  • 原文地址:https://www.cnblogs.com/lokiii/p/10928043.html
Copyright © 2011-2022 走看看