티스토리 뷰
[CF 1512E] Permutation by Sum - 1600
문제 요약 :
1~n수 중에서 (r-l+1)개 중복없이 뽑아서 s만들 수 있는지를 묻고 있다.
문제 풀이 :
n부터 1씩 줄여나가면서 누적합을 쌓아가면서 s를 만든다. 이때 만들어진 수의 집합은 최소의 개수이므로 (r-l+1)개보다 적거나 같을 것이다. 만약 크다면 s를 만들 수 없다는 뜻이다.
개수를 늘리기 위해서는 작은 값부터 2개로 쪼개면 된다. 예를 들어 x라는 값을 쪼갠다면 (1,x-1) 또는 (2,x-2) 또는 (3,x-3)...이런 식이다. 이때 쪼개진 결과로 나오는 두 개의 값은 초기 집합과 겹치면 안된다. 겹치지 않는 것이 확인이 된다면 set에서 두 값을 insert 해주고 원래 x값은 삭제해준다. 가장 작은 값부터 쪼개기 때문에 연속적으로 시행해도 계속 작아짐이 보장된다.
#include <bits/stdc++.h>
using namespace std;
/************************Contest Template**************************/
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<long long,long long> pll;
#define FASTIO ios_base::sync_with_stdio(false);cin.tie(0);
struct S{
int a,b; S(){}S(int _a,int _b)
{ a=_a; b=_b; }
const bool operator<(const S &o) const{
return a<o.a;}
};
string exm;
inline void exf(void){ cout<<exm<<"\n"; exit(0); }
template <typename T>
inline void showAll(vector<T> &v,string sep=""){
for(T &here:v) cout<<here<<sep;}
template <typename T>
inline void showAll(T a[],int st,int end,string sep=""){
for(int i=st ; i<=end ; i++) cout<<a[i]<<sep; }
template <typename T>
inline vector<int> int_seperation(T N,int d=10){
vector<int> v; while(N){v.push_back(N%d); N/=d;}
reverse(v.begin(),v.end()); return v; }
/************************Contest Template**************************/
const int SIZE=200009;
int main(){
int t; scanf("%d",&t);
while(t--){
int n,l,r,s; scanf("%d %d %d %d",&n,&l,&r,&s);
set<int> si;
int mn = 0,mx = 0;
for(int i=1 ; i<=r-l+1 ; i++){
mn += i;
}
for(int i=n ; i>=n-(r-l+1)+1 ; i--){
mx += i;
}
if(s>mx || s<mn) {
printf("-1\n");
continue;
}
for(int i=n,sum=0 ; i>=1 ; i--){
if(sum + i <= s) {
si.insert(i);
sum += i;
}
}
auto it = si.begin();
while(si.size() != r-l+1){
int x = *it;
int check = 0;
for(int j=1 ; j<=x-1 ; j++){
if(j!=x-j && si.count(j)==0 && si.count(x-j)==0){
si.erase(x);
si.insert(j);
si.insert(x-j);
check = 1;
it = si.begin();
break;
}
}
if(!check) it = next(it);
}
int ans[509]={0};
set<int> unused;
for(int i=1 ; i<=n ; i++) unused.insert(i);
for(int x : si){
if(x > 0) unused.erase(x);
}
for(int i=1 ; i<=n ; i++){
if(i>=l && i<=r){
ans[i] = *si.begin();
si.erase(ans[i]);
}
else {
ans[i] = *unused.begin();
unused.erase(ans[i]);
}
}
set<int> test;
for(int i=1 ; i<=n ; i++){
if(test.count(ans[i])) assert(0);
else test.insert(ans[i]);
}
showAll(ans,1,n," ");
printf("\n");
}
}
'Problem Solving > Implementation' 카테고리의 다른 글
[CF 1208B] Uniqueness (좌표압축) (0) | 2019.10.15 |
---|---|
[CF 1154E] Two Teams (0) | 2019.08.20 |
[Codeforces 962D] Merge Equals (0) | 2019.05.20 |
[Codeforces 1163B2] Cat Party (Hard Edition) (0) | 2019.05.11 |
[Codeforces 1108E1] Array and Segments (Easy version) (0) | 2019.05.06 |
댓글