Brief Intro:
给你n个数,每个数有2*CNT[i]个,让你构造一个序列
使得最终的Y值为W(其余见题面)
Solution:
就是一道纯构造的题目:
先把特殊情况特殊处理,接下来考虑一般情况:
如果让每种数字都连续放置,则对于每两个相同的A[i],Y则加一
要想最终Y=W,则要将多余的去除。于是这样构造:
A:1........1211...112 B:11..122..233...344...4.....nn
最终序列分为A段和B段,其中A段仅能使Y+=2,同时去除多余的项
剩余的先计算好后在B中连续放置即可
Code:
#include <bits/stdc++.h> using namespace std; template<class T> inline void putnum(T x) { if(x<0)putchar('-'),x=-x; register short a[20]={},sz=0; while(x)a[sz++]=x%10,x/=10; if(sz==0)putchar('0'); for(int i=sz-1;i>=0;i--)putchar('0'+a[i]); putchar(' '); } int n,w,dat[1005],res[1005],sum=0,pos=-1; int main() { cin >> n >> w; for(int i=1;i<=n;i++) { cin >> dat[i],sum+=dat[i]; if(dat[i]==1) pos=i; } if(w<1 || w>sum || (n==1 && w!=sum) || (w==1 && pos==-1)) return puts("No"),0; puts("Yes"); if(n==1) for(int i=1;i<=2*dat[1];i++) putnum(1); else if(w==1) { dat[pos]--; putnum(pos); for(int i=1;i<=n;i++) for(int j=1;j<=2*dat[i];j++) putnum(i); putnum(pos); } else { w=w-2;dat[1]--;dat[2]--; for(int i=1;i<=n;i++) while(w && dat[i]) res[i]++,w--,dat[i]--; putnum(1); for(int i=2;i<=n;i++) for(int j=1;j<=2*dat[i];j++) putnum(i); putnum(1);putnum(2); for(int i=1;i<=2*dat[1];i++) putnum(1); putnum(2); for(int i=1;i<=n;i++) for(int j=1;j<=2*res[i];j++) putnum(i); } return 0; }
Review:
对于构造题,要利用性质去除不符合条件的项