您的位置:首页 > 其它

Codeforces 8VC Venture Cup 2017 - Elimination Round

2017-01-19 22:45 429 查看

C. PolandBall and Forest

简单并查集,把相关节点合并即可。

#include <bits/stdc++.h>

using namespace std;

#define ll long long

int p[10010];
int a[10010];

int find(int x){
if(x!=p[x])p[x]=find(p[x]);
return p[x];
}

void _union(int a,int b){
int fa=find(a);
int fb=find(b);
p[fa]=fb;
}

int main(){
int n;
cin>>n;

for(int i=1;i<=n;i++){
p[i] = i;
cin>>a[i];
}

for(int i=1;i<=n;i++){
_union(i,a[i]);
}

set<int> S;

for(int i=1;i<=n;i++){
S.insert(find(i));
}

cout<<S.size()<<endl;

return 0;
}


D. PolandBall and Polygon

思考一下,可以发现,每条线的跨度是一样的,所以,只有与当前连线距离小于k的已存在的连线,会与当前连线相交,用数据结构维护一下,每次查询符合要求的线已有多少条。注意k>n/2时的情形。

#include <bits/stdc++.h>

using namespace std;

#define ll long long

const int maxn = 1000010;

int n,k;

int c[maxn];

inline int lowbit(int x){
return x&(-x);
}

void update(int pos){
while(pos<=n){
c[pos]++;
pos+=lowbit(pos);
}
}

int query(int pos){
int re=0;
while(pos){
re+=c[pos];
pos-=lowbit(pos);
}
return re;
}

int Q(int l,int r){
if(r >= l){
return query(r) - query(l-1);
}else{
return Q(1,r) + Q(l,n);
}
}

int main(){
cin>>n>>k;
if(k > n/2){
k = n-k;
}

int pos = 0;
update(1);
ll ans = 1;

for(int i=0;i<n;i++){
int l = pos-k+1;
int r = pos+k-1;

pos += k;
pos %= n;

if(l<0){
l+=n;
}
if(r>=n){
r-=n;
}

int tmp = Q(l+1,r+1)-1;
ans += (tmp+1);

printf("%I64d ",ans);
update(pos+1);
}
return 0;
}


E. PolandBall and White-Red graph

构造题。可以发现,只有k=2和k=3时可能有解。k=2时,一个大环就是解,k=3时,造一个仅少一条边的二分图即可。

#include <bits/stdc++.h>

using namespace std;

#define ll long long

int main(){
int n,k;
cin>>n>>k;
if(n==4){
if(k!=3){
cout<<-1<<endl;
}else{
int half = n/2;
int half2 = n-half;
cout<<half*half2 - 1<<endl;
for(int i=1;i<=half;i++){
for(int j=half+1;j<=n;j++){
if(!(i==1 && j==half+1))printf("%d %d\n",i,j);
}
}
}
}else if(n>4){
if(k == 2){
cout<<n-1<<endl;
for(int i=1;i<n;i++){
cout<<i<<" "<<i+1<<endl;
}
}else if(k == 3){
int half = n/2;
int half2 = n-half;
cout<<half*half2 - 1<<endl;
for(int i=1;i<=half;i++){
for(int j=half+1;j<=n;j++){
if(!(i==1 && j==half+1))printf("%d %d\n",i,j);
}
}
}else{
cout<<-1<<endl;
}
}else{
cout<<-1<<endl;
}
return 0;
}


F. PolandBall and Gifts

容易看出,最大值贪心可解,最小值是个背包问题,直接跑多重背包,压到bieset里面优化。

#include <bits/stdc++.h>

using namespace std;

#define ll long long

const int maxn = 1000010;
int p[maxn];
bool vis[maxn];

int main(){
int n,k;
cin>>n>>k;

for(int i=1;i<=n;i++){
scanf("%d",&p[i]);
}

vector<int> cir;
for(int i=1;i<=n;i++){
if(!vis[i]){
int t = i;
int len = 0;
while(!vis[t]){
vis[t] = 1;
t = p[t];
len++;
}
cir.push_back(len);
}
}
sort(cir.begin(),cir.end());

int MAX = 0;
int kk = k;
for(int i=0;i<cir.size();i++){
int tmp = cir[i];
while(tmp >= 2 && kk > 0){
MAX += 2;
kk--;
tmp -= 2;
}
}
MAX += kk;
MAX = min(MAX,n);

vector<int> vec;
cir.push_back(-1);
int s = 0;
for(int i=1;i<cir.size();i++){
while(cir[i] == cir[i-1]){
i++;
}
int t = i - s;
s = i;
int j = 0;
while(t){
int tmp = min(1<<j,t);
t -= tmp;
j++;
vec.push_back(cir[i-1]*tmp);
}
if(cir[i] == -1){
break;
}
}

bitset<maxn> bs[2];
int cur = 0, pre = 1;
bs[cur][0] = 1;
for(int i=0;i<vec.size();i++){
swap(cur,pre);
bs[cur] = bs[pre] | (bs[pre]<<vec[i]);
}
int MIN = k + 1 - bs[cur][k];

cout<<MIN<<" "<<MAX<<endl;

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  codeforces 8VC