Sheryl's ACM

一条默默划水的咸鱼

导航

Codeforces Round#408 Div.2

A. Buying A House

题面

Zane the wizard had never loved anyone before, until he fell in love with a girl, whose name remains unknown to us.

The girl lives in house m of a village. There are n houses in that village, lining in a straight line from left to right: house 1, house 2, ..., house n. The village is also well-structured: house i and house i + 1 (1 ≤ i < n) are exactly 10 meters away. In this village, some houses are occupied, and some are not. Indeed, unoccupied houses can be purchased.

You will be given n integers a1, a2, ..., an that denote the availability and the prices of the houses. If house i is occupied, and therefore cannot be bought, then ai equals 0. Otherwise, house i can be bought, and ai represents the money required to buy it, in dollars.

As Zane has only k dollars to spare, it becomes a challenge for him to choose the house to purchase, so that he could live as near as possible to his crush. Help Zane determine the minimum distance from his crush's house to some house he can afford, to help him succeed in his love.

题意

Zane有k元钱,问买得起的房子 离他家最近的距离为多少。

代码

#include<bits/stdc++.h>
using namespace std;

int n,m,k;
int a[1000];
int ans;

int main()
{
    ios::sync_with_stdio(false);
	cin>>n>>m>>k;
	ans=10000;
	for (int i=1;i<=n;i++) cin>>a[i];
	
	for (int i=1;i<=n;i++) if (a[i] && a[i]<=k && i!=m) ans=min(ans,10*abs(i-m));
	
	cout<<ans;
}

B. Find The Bone

题面

outputstandard output
Zane the wizard is going to perform a magic show shuffling the cups.

There are n cups, numbered from 1 to n, placed along the x-axis on a table that has m holes on it. More precisely, cup i is on the table at the position x = i.

The problematic bone is initially at the position x = 1. Zane will confuse the audience by swapping the cups k times, the i-th time of which involves the cups at the positions x = ui and x = vi. If the bone happens to be at the position where there is a hole at any time, it will fall into the hole onto the ground and will not be affected by future swapping operations.

Do not forget that Zane is a wizard. When he swaps the cups, he does not move them ordinarily. Instead, he teleports the cups (along with the bone, if it is inside) to the intended positions. Therefore, for example, when he swaps the cup at x = 4 and the one at x = 6, they will not be at the position x = 5 at any moment during the operation.

Zane’s puppy, Inzane, is in trouble. Zane is away on his vacation, and Inzane cannot find his beloved bone, as it would be too exhausting to try opening all the cups. Inzane knows that the Codeforces community has successfully helped Zane, so he wants to see if it could help him solve his problem too. Help Inzane determine the final position of the bone.

题意

骨头在1,每次交换两个帽子,骨头遇到洞直接掉下去。问最终骨头在哪里。

跟着模拟就好了

代码

#include<bits/stdc++.h>
using namespace std;

int n,m,k;
int a[2000010];
int x,y;
int now;

int main()
{
    ios::sync_with_stdio(false);
	cin>>n>>m>>k;
	now=1;
	for (int i=1;i<=m;i++)
	{
		cin>>x;
		a[x]=1;
	}
	
	if (a[now]) return 0*puts("1");
	for (int i=1;i<=k;i++)
	{
		cin>>x>>y;
		if (now==x) now=y;
		else if (now==y) now=x;
		else continue;
		if (a[now]) 
		{
			cout<<now<<endl;
			return 0;
		}
	}
	
	cout<<now<<endl;
	return 0;
}

C. Bank Hacking

题面

Although Inzane successfully found his beloved bone, Zane, his owner, has yet to return. To search for Zane, he would need a lot of money, of which he sadly has none. To deal with the problem, he has decided to hack the banks.

There are n banks, numbered from 1 to n. There are also n - 1 wires connecting the banks. All banks are initially online. Each bank also has its initial strength: bank i has initial strength ai.

Let us define some keywords before we proceed. Bank i and bank j are neighboring if and only if there exists a wire directly connecting them. Bank i and bank j are semi-neighboring if and only if there exists an online bank k such that bank i and bank k are neighboring and bank k and bank j are neighboring.

When a bank is hacked, it becomes offline (and no longer online), and other banks that are neighboring or semi-neighboring to it have their strengths increased by 1.

To start his plan, Inzane will choose a bank to hack first. Indeed, the strength of such bank must not exceed the strength of his computer. After this, he will repeatedly choose some bank to hack next until all the banks are hacked, but he can continue to hack bank x if and only if all these conditions are met:

  • Bank x is online. That is, bank x is not hacked yet.
  • Bank x is neighboring to some offline bank.
  • The strength of bank x is less than or equal to the strength of Inzane's computer.

Determine the minimum strength of the computer Inzane needs to hack all the banks.

题意

访问一个树上的点会导致他相邻的点和距离为二的点的权值+1,并将该点删去。问最终访问所有节点的权值最小值为多少。

官方题解

答案显然为max{ai}或者max{ai}+1或者max{ai}+2

我们只要对每个点进行枚举就可以了

对于一个点:

  • 如果所有最大点与该点相邻,ans=min(ans,maxval+1)
  • 如果有最大点相邻,且有最大点与该点距离为2,ans=min(ans,maxval+2)
  • 如果没有最大点相邻,有次大点相邻,ans=min(ans,maxval)
  • 如果没有最大点相邻,有次大点相邻,且有次大点距离为2,ans=min(ans,maxval+1)

官方代码(改)

#include <bits/stdc++.h>
using namespace std;

int n;
int a[300005];
vector<int> way[300005];
int maxval;
int u,v;
int x,y;
int res;
 
int main()
{
    cin>>n;
    maxval=-1e9;
    for(int i=1; i<=n; i++) 
	{
		cin>>a[i];
		maxval=max(maxval,a[i]);
	}
    for(int i=0; i<n-1; i++)
	{
        cin>>u>>v;
        way[u].push_back(v);
        way[v].push_back(u);
    }
    
    
    for(int i=1;i<=n;i++)
	{
        if (a[i] == maxval) x++;
        else if(a[i] == maxval-1) y++;
    }
 
    res=maxval+2;
 
    for(int i=1; i<=n; i++)
	{
        if (a[i] == maxval) x--;
        else if (a[i] == maxval-1) y--;
        
        for (int j=0;j<way[i].size();j++)
		{
            int pos = way[i][j];
            if(a[pos] == maxval) x--, y++;
            else if(a[pos] == maxval-1) y--;
        }
 
        if(x == 0)
		{
            res = min(res, maxval+1);
            if(y == 0) res = min(res, maxval);
        }
 
        if(a[i] == maxval) x++;
        else if(a[i] == maxval-1) y++;
        
        for(int j=0; j<way[i].size(); j++)
		{
            int pos = way[i][j];
            if(a[pos] == maxval) x++, y--;
            else if(a[pos] == maxval-1) y++;
        }
 
    }
 
    cout<<res;
 
    return 0;
}

D. Police Stations

题面

Inzane finally found Zane with a lot of money to spare, so they together decided to establish a country of their own.

Ruling a country is not an easy job. Thieves and terrorists are always ready to ruin the country's peace. To fight back, Zane and Inzane have enacted a very effective law: from each city it must be possible to reach a police station by traveling at most d kilometers along the roads.

There are n cities in the country, numbered from 1 to n, connected only by exactly n - 1 roads. All roads are 1 kilometer long. It is initially possible to travel from a city to any other city using these roads. The country also has k police stations located in some cities. In particular, the city's structure satisfies the requirement enforced by the previously mentioned law. Also note that there can be multiple police stations in one city.

However, Zane feels like having as many as n - 1 roads is unnecessary. The country is having financial issues, so it wants to minimize the road maintenance cost by shutting down as many roads as possible.

Help Zane find the maximum number of roads that can be shut down without breaking the law. Also, help him determine such roads.

题意

问该图有几条边是多余的,可以删去哪几条边

官方题解

首先图都是合法的,我们用bfs来访问所有点,如果访问到该点已经被访问,说明该条边就是多余的。

代码

#include <bits/stdc++.h>
using namespace std;

int n,k,d;
queue<pair<int, int> > q;
vector<pair<int, int> > way[300005];
int v[300005];
int res[300005];
int p;
 
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
    cin>>n>>k>>d;
    
    for (int i=0; i<k; i++)
	{
        cin>>p;
        q.push({p, 0});
    }
    for (int i=0; i<n-1; i++)
	{
		int u,v;
        cin>>u>>v;
        way[u].push_back({v, i+1});
        way[v].push_back({u, i+1});
    }
    
    while (!q.empty())
	{
        int pos = q.front().first;
        int from = q.front().second;
        q.pop();
        if (v[pos]) continue;
        v[pos] = 1;
        for (int i=0;i<way[pos].size();i++) 
			if(way[pos][i].first != from)
			{
            	if (v[way[pos][i].first]) res[way[pos][i].second] = 1;
            	else q.push({way[pos][i].first, pos});
       		}
    }
    int rescnt=0;
    for(int i=1; i<=n-1; i++) if(res[i]) rescnt++;
    cout<<rescnt<<endl;
    for(int i=1; i<=n-1; i++) if(res[i]) cout<<i<<" ";
    return 0;
}

E. Exam Cheating

题面

Zane and Zane's crush have just decided to date! However, the girl is having a problem with her Physics final exam, and needs your help.

There are n questions, numbered from 1 to n. Question i comes before question i + 1 (1 ≤ i < n). Each of the questions cannot be guessed on, due to the huge penalty for wrong answers. The girl luckily sits in the middle of two geniuses, so she is going to cheat.

However, the geniuses have limitations. Each of them may or may not know the answers to some questions. Anyway, it is safe to assume that the answers on their answer sheets are absolutely correct.

To make sure she will not get caught by the proctor, the girl will glance at most p times, each time looking at no more than k consecutive questions on one of the two geniuses' answer sheet. When the girl looks at some question on an answer sheet, she copies the answer to that question if it is on that answer sheet, or does nothing otherwise.

Help the girl find the maximum number of questions she can get correct.

题意

有人想考试作弊,他能左右偷看。

有A,B两个一维点集合,用P根线去覆盖最多的点,最多能覆盖多少点。

官方题解

我们用dp[i][j][x][y]来表示:

  • 前i道题目
  • 使用了j次偷看机会
  • person1还可以偷看连续的x道题目
  • person2还可以偷看连续的y道题目

由于空间不足,我们使用滚动数组

官方代码(改)

#include <bits/stdc++.h>
using namespace std;
 
int A[1005], B[1005];
int dp[2][1005][55][55];
int n,p,k;
int r,x,s;
 
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	
	cin>>n>>p>>k;
    if(k == 0)
	{
		printf("0");
		return 0;
	}
    if (p> 2*((n+k-1)/k)) p = 2*((n+k-1)/k); 
    
    cin>>r;
    for (int i=0;i<r;i++)
	{
        cin>>x;
        A[x] = 1;
    }
    
    cin>>s;
    for (int i=0;i<s;i++)
	{
        cin>>x;
        B[x] = 1;
    }
    
    
    for (int i=0;i<2;i++)
		for (int j=0;j<1005;j++) 
			for (int k=0;k<55;k++) 
				for (int p=0;p<55;p++) 
					dp[i][j][k][p] = -1e9;
    dp[0][0][0][0] = 0;
    
    
    for(int i=1; i<=n; i++)
	{
        int cur = i&1, prev = !cur;
        
        
        for (int j=1;j<=p;j++) 
			dp[cur][j][k-1][0] = max(dp[cur][j][k-1][0], dp[prev][j-1][0][0] + A[i]);
        for (int j=1; j<=p; j++) 
			for (int a=0; a<k-1; a++) 
				dp[cur][j][a][0] = max(dp[cur][j][a][0], dp[prev][j][a+1][0] + A[i]);
 
 
        for (int j=1;j<=p;j++) 
			dp[cur][j][0][k-1] = max(dp[cur][j][0][k-1], dp[prev][j-1][0][0] + B[i]);
        for (int j=1;j<=p;j++) 
			for (int b=0;b<k-1;b++) 
				dp[cur][j][0][b] = max(dp[cur][j][0][b], dp[prev][j][0][b+1] + B[i]);
 

        for (int j=1;j<=p;j++) 
			for (int a=0;a<k-1;a++) 
				dp[cur][j][a][k-1] = max(dp[cur][j][a][k-1], dp[prev][j-1][a+1][0] + (A[i]|B[i]));
        for (int j=1;j<=p;j++) 
			for (int b=0;b<k-1;b++) 
				dp[cur][j][k-1][b] = max(dp[cur][j][k-1][b], dp[prev][j-1][0][b+1] + (A[i]|B[i]));
        for (int j=2;j<=p;j++) 
			for (int a=0;a<k-1;a++) 
				for (int b=0;b<k-1;b++) 
					dp[cur][j][a][b] = max(dp[cur][j][a][b], dp[prev][j][a+1][b+1] + (A[i]|B[i]));
 

        for (int j=0;j<=p;j++) 
			dp[cur][j][0][0] = max(dp[cur][j][0][0], dp[prev][j][0][0]);
 
        for (int j=0;j<=p;j++) 
			for (int a=0;a<k;a++) 
				for(int b=0;b<k;b++) 
					dp[prev][j][a][b] = -1e9;
    }
    int res = -1e9;
    for (int i=0; i<=p; i++) 
		for (int j=0; j<k; j++) 
			for (int a=0; a<k; a++) 
				res = max(res, dp[n&1][i][j][a]);
    cout<<res;
    return 0;
}

F. Sequence Recovery

题面

Zane once had a good sequence a consisting of n integers a1, a2, ..., an — but he has lost it.

A sequence is said to be good if and only if all of its integers are non-negative and do not exceed 109 in value.

However, Zane remembers having played around with his sequence by applying m operations to it.

There are two types of operations:

  1. Find the maximum value of integers with indices i such that l ≤ i ≤ r, given l and r.

  2. Assign d as the value of the integer with index k, given k and d.

After he finished playing, he restored his sequence to the state it was before any operations were applied. That is, sequence a was no longer affected by the applied type 2 operations. Then, he lost his sequence at some time between now and then.

Fortunately, Zane remembers all the operations and the order he applied them to his sequence, along with the distinct results of all type 1 operations. Moreover, among all good sequences that would produce the same results when the same operations are applied in the same order, he knows that his sequence a has the greatest cuteness.

We define cuteness of a sequence as the bitwise OR result of all integers in such sequence. For example, the cuteness of Zane's sequence a is a1 OR a2 OR ... OR an.

Zane understands that it might not be possible to recover exactly the lost sequence given his information, so he would be happy to get any good sequence b consisting of n integers b1, b2, ..., bn that:

  1. would give the same results when the same operations are applied in the same order, and

  2. has the same cuteness as that of Zane's original sequence a.

If there is such a sequence, find it. Otherwise, it means that Zane must have remembered something incorrectly, which is possible.

题意

给一堆操作,求原来可能的数组

想到用线段树维护

官方题解

线段树上搞事。初始化先将数字变为一个很大的值,然后对于操作1,将数组变为t[i]=min(t[i],val)

官方是一个很诡异的线段树,我从来没见过,感觉涨姿势了。

为什么让每个点优先存大数,如果有其他的区间来覆盖,那么该点存小数。对于原来区间的不覆盖部分不影响源区间的最大值,如果刚刚好覆盖会导致矛盾,在第二次遍历的时候会查出错误

这道题通过的人少在于 前面的题目难度较大,代码量也较大,这道题的难度虽然较小,但是代码复杂度也偏大。

代码

//这道题建议参考官方代码,本人没有试验过,有点晚了,先睡了,日后(永远不)再补
//http://ideone.com/FfnJyp

练习赛

C和D都没有做出来。。

大概是不在比赛状态,有点放水。。

比赛链接

http://codeforces.com/contest/796

posted on 2017-05-18 04:37  EDGsheryl  阅读(309)  评论(0编辑  收藏  举报