http://codeforces.com/problemset/problem/1214/E
本来看到是构造题都想直接点外卖吃饭了的,一直觉得这辈子都做不出构造题,没想到脑补了一种做法过了,不知道是不是正解。
按照d从大到小排序,然后从前向后安排,先构造出一条尽可能长的链,我们将奇数点记为a[i],偶数点记为b[i]。
如果当前cnt这个位置可以放之前已经放的某一个a[id]的b[id],也就是cnt离a[id]的距离恰好的d[id],那么就放b[id],如果已经小了,那么b[id]就连向链那个位置已经放的别的数字。
一直构造到a[1...n]全部放完,长链无法再变长时,对于那些还没有安排的b[id],我们选择a[id]所在的位置向前找第d[id]个位置放b[id]。由于是按照d[id]拍过序的,所以后面要安排的d[id]都很小。
其实有更优的构造方法是对于后面无法安排的那些a[id],按照d[id]从小到大再排一次序,那么d[id]在越后面,就越不容易出错。
不过不考虑这么多的做法也过了。。。
#include<bits/stdc++.h>
#define maxl 500010
using namespace std;
int n,m,ans,cnt,tot;
struct node
{
int d,id;
}a[maxl];
int b[maxl],dis[maxl],dy[maxl];
char s[maxl];
bool in[maxl];
vector <int> add[maxl];
typedef pair<int,int> p;
priority_queue<p,vector<p>,greater<p> > q;
inline bool cmp(const node &x,const node &y)
{
return x.d>y.d;
}
inline void prework()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i].d);
a[i].id=i;dis[i]=a[i].d;
}
sort(a+1,a+1+n,cmp);
}
inline void mainwork()
{
cnt=1;p d;
for(int i=1;i<=n;i++)
{
b[cnt]=2*a[i].id-1;dy[a[i].id]=cnt;
q.push(make_pair(cnt+a[i].d,a[i].id));
++cnt;
while(!q.empty())
{
d=q.top();
if(d.first==cnt)
{
q.pop();
b[cnt]=2*d.second;
++cnt;
}
else
if(d.first<cnt)
{
q.pop();
add[d.first-1].push_back(2*d.second);
}
else
break;
}
}
cnt--;
int id;
while(!q.empty())
{
d=q.top();q.pop();
id=dy[d.second]-dis[d.second];
add[id+1].push_back(2*d.second);
}
}
inline void print()
{
for(int i=1;i<cnt;i++)
printf("%d %d\n",b[i],b[i+1]);
for(int i=1;i<=cnt;i++)
{
int l=add[i].size();
for(int j=0;j<l;j++)
printf("%d %d\n",b[i],add[i][j]);
}
}
int main()
{
int t=1;
//scanf("%d",&t);
for(int i=1;i<=t;i++)
{
prework();
mainwork();
print();
}
return 0;
}