1. 程式人生 > >Avito Cool Challenge 2018 B - Farewell Party

Avito Cool Challenge 2018 B - Farewell Party

題目大意:

有n個人 

接下來一行n個數a[i] 表示第i個人描述其他人有a[i]個的帽子跟他不一樣

帽子編號為1~n 如果所有的描述都是正確的

輸出possible 再輸出一行b[i] 表示第i個人的帽子的編號

如果存在矛盾 輸出impossible

 

如果存在p 個人都描述有q個人跟他們的帽子不一樣

此時若 p+q=n 說明正確且這p個人的帽子都一樣

如  

a[] = 3 3 2 2 2 ,此時一種解為 b[] = 1 1 2 2 2

存在p=2個人描述有q=3個人跟他們不一樣 說明這兩個人的帽子編號是一樣的

 

但是這種方法存在一種特殊情況

a[] = 4 4 4 4 4 4 ,如果按上面的解法此時則無解

但是實際上存在一種解 即 b[] = 1 1 2 2 3 3

不過可以看出來這種特殊情況 每種帽子對應的人數是一樣多的

那麼此時存在p=6個人描述有q=4個人跟他們不一樣 

​可以得到每種帽子對應人數為 t

判斷一下p能不能整除t 若能說明描述正確

否則 描述矛盾 impossible

 

題目要求對應第i個人輸出帽子編號  。。英語渣給跪了 錯在這裡以為不需要對應

不需要對應很好處理 需要對應其實也不難

開了一排棧~

第一種情況 在ans[q]壓入一種編號p個

特殊情況 在ans[q]壓入p/t種編號t個

最後從每個人的描述arr[i]裡取ans[arr[i]]的棧頂輸出就行了

 

#include <bits/stdc++.h>
#define LL long long
#define INF 0x3f3f3f3f
using namespace std;
int n, arr[100005];
stack <int> ans[100005];
int main()
{
    while(~scanf("%d",&n)) {
        for(int i=1;i<=n;i++)
            
while(!ans[i].empty()) ans[i].pop(); map <int,int> mp; mp.clear(); for(int i=0;i<n;i++) { scanf("%d",&arr[i]); if(!mp.count(arr[i])) mp[arr[i]]=1; else mp[arr[i]]++; // 記錄描述為q的人有多少個 } map <int,int> :: iterator it; bool OK=1; int id=1; for(it=mp.begin();it!=mp.end();it++) { int q=(*it).first, p=(*it).second; if(p+q!=n) { int t=n-q; if(p%t==0) { // 特殊情況 for(int i=0;i<p/t;i++) { // 壓入p/t種 for(int j=0;j<t;j++) // 每種t個 ans[q].push(id); id++; } } else { OK=0; break; } } else { // while(p--) ans[q].push(id); // 壓入一種編號p個 id++; } } if(OK) { printf("Possible\n"); for(int i=0;i<n;i++) { printf("%d ",ans[arr[i]].top()); ans[arr[i]].pop(); } printf("\n"); } else printf("Impossible\n"); } return 0; }
View Code