Codeforces 2017, X Samara Regional Intercollegiate Programming Contest

本文解析了多项编程竞赛题目,包括括号匹配问题、字符串搜索、概率计算等,提供了详细的算法思路与实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

A. Streets of Working Lanterns - 2
time limit per test
2.0 s
memory limit per test
256 MB
input
standard input
output
standard output

Policeman Anatoliy again monitors a lair of unorganized criminal group spreading prohibited Asian drawings. Presently the criminals are also sharing wireless Internet which can be used anonymously by whoever wants to. The lair still has only one entrance, which is also an exit. When someone enters into the lair, Anatoliy writes an opening round bracket in his notepad, and when someone comes out, he writes a closing round bracket.

Anatoliy decided to refrain from eating donuts in order not to spoil the records just like the previous time, but nevertheless, when he tore a sheet out of a notepad to file it to a criminal case, accidentally tore it into pieces. He doesn't want his boss to shout on him, so he must restore his records by connecting pieces in the right order. It's good for him that the layout of notepad sheets allows to determine where top and bottom sides of these pieces are. Anatoliy ensured that the lair of criminals was empty before he started the surveillance and after he ended it.

Input

The first line contains a single integer n (1 ≤ n ≤ 2·105) — the number of pieces of paper with opening and closing round brackets written on them.

The next n lines contain only characters «(» and «)» — these are the strings written on pieces. The total number of brackets does not exceed 2·105.

Output

If the given pieces can be connected so that the resulting string does not contradict the statement, output in the first line «YES» without quotes. In the second line output n integers separated by spaces — the numbers of pieces in the order they must be connected. The pieces are numbered from one in the order they are mentioned in the input.

If Anatoliy messed up something and the given pieces cannot form the correct record, output in the only line «NO» without quotes.


首先一行中可以抵消掉的左右括号先抵消掉,然后分四种情况。
1:只剩下左括号的要先放。
2:既有左括号又有右括号,因为既然左右括号没有抵消,那么
右括号一定在左,左括号一定在右,第二种情况选取左括号多于
右括号的情况,所说这种情况放进去之后左括号一定是增加的,
但是由于右括号在前,所以为了避免右括号还没有放完左括号
就减到0的情况,先放右括号最少的,因为每放一排左括号都
是增加的,这样有利于放后面右括号多的排。
3:右括号多余左括号,这是最谜的一种情况,开始仿照2的思路,
先放右括号多的,因为总趋势是左括号在减少,右括号多的现在
放不下以后一定放不下,这样提交之后样例过了70组。后来想了
一下,这样也不一定就是最优的。
比如:
4
(((((
)))((
))))(
)
这种情况1,3,2,4是不行的,但是1,2,3,4是可以的。
虽说右括号多的现在放不下以后一定放不下,但是现在能放下,下一步
也能放下,那么这一步放就不一定是最优的,这就是问题所在。如上样例
先放3会导致左括号减少的太多,然后2就放不下了。
第三种情况应该是按左括号多的排序,至今也没想明白为什么。此问题
暂且搁置。
第四种情况便是只有右括号
代码:

#include<bits/stdc++.h>
char t[200003];
int a[200003],c[200003];
using namespace std;
struct node
{
    int dec,z,y;
};
node b[200004],d[200004];
bool cmp(node a,node b)
{
    if(a.y!=b.y)return a.y<b.y;
    return a.z>b.z;
}
bool cmp1(node a,node b)
{
    if(a.z!=b.z)return a.z>b.z;
    return a.y>b.y;
}
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        int i,j,A=0,B=0,C=0,D=0,s=0,s2=0;
        for(i=1; i<=n; i++)
        {
            scanf("%s",&t);
            int L=strlen(t);
            int z=0,y=0;
            for(j=0;j<L;j++)
            {
                if(t[j]=='(')z++;
                else
                {
                    if(z)z--;
                    else y++;
                }
            }
            if(y==0&&z!=0)a[A++]=i,s=s+z;
            else if(y!=0&&z==0)c[C++]=i,s2=s2-y;
            else if(z-y>=0)b[B].dec=i,b[B].z=z,b[B++].y=y;
            else d[D].dec=i,d[D].z=z,d[D++].y=y;
        }
        sort(b,b+B,cmp);
        bool bb=1;
        for(i=0;i<B;i++)
        {
            s=s-b[i].y;
            if(s<0)
            {
                bb=0;break;
            }
            s=s+b[i].z;
        }
        if(bb==0)
        {
            printf("NO\n");
            continue;
        }
        sort(d,d+D,cmp1);
        for(i=0;i<D;i++)
        {
            s=s-d[i].y;
            if(s<0)
            {
                bb=0;break;
            }
            s=s+d[i].z;
        }
        if(bb==0||s+s2!=0)
        {
            printf("NO\n");
            continue;
        }
        printf("YES\n");
        for(i=0;i<A;i++)
        printf("%d ",a[i]);
        for(i=0;i<B;i++)
            printf("%d ",b[i].dec);
        for(i=0;i<D;i++)
            printf("%d ",d[i].dec);
        for(i=0;i<C;i++)
            printf("%d ",c[i]);
        printf("\n");
    }
    return 0;
}



这题数据范围较小,直接暴力也没关系,但是刚刚学了KMP,就顺便用一下
这题就是找happiness,可以交换两个字母,那么如果有两个或以下的
happiness,就一定可以隐藏 ,但是有一个问题就是不存在happiness
的时候也要交换两个字母,这样要避免交换后出现happiness的情况
若不来不存在,可以找两个相同的字母交换,这样不会影响,若不存在
相同字母,则一定不会出现happiness,随意交换即可。
代码:

#include<bits/stdc++.h>
using namespace std;
char text[200006],p[]="happiness";
int next[200006],tp[200];
bool mp[200];
void compulate()
{
    int L=strlen(p);
    next[0]=0;
    int i,s=0,k=0;
    for(i=1;i<L;i++)
    {
        while(k!=0&&p[i]!=p[k])
            k=next[k];
        if(p[i]==p[k])
            k++;
        next[i]=k;
    }
}
int main()
{
    compulate();
    while(~scanf("%s",&text))
    {
        int i,j,L1=strlen(text),L2=strlen(p);
        int s=0,q=0,x=-1,y=-1,ans=0;
        while(s<L1)
        {
            q=next[q];
            while(q<L2&&p[q]==text[s])
                s++,q++;
            if(q==0)s++;
            else if(q==L2)
            {
                if(x==-1)x=s-L2+1;
                y=s-L2+2;
                ans++;
            }
        }
        if(ans>=3) printf("NO\n");
        else if(ans==1||ans==2) printf("YES\n%d %d\n",x,y);
        else
        {
            bool bb=0;
            memset(mp,0,sizeof(mp));
            for(i=0;i<L1;i++)
            {
                if(mp[text[i]])
                {
                    printf("YES\n");
                    printf("%d ",tp[text[i]]+1);
                    printf("%d\n",i+1);
                    bb=1;break;
                }
                mp[text[i]]=1;
                tp[text[i]]=i;
            }
            if(!bb)printf("YES\n1 2\n");
        }
    }
    return 0;
}

C. Urn with Balls
time limit per test
2.0 s
memory limit per test
256 MB
input
standard input
output
standard output

Megabrain has usual problems with the occupiers: he is captured again and is forced to solve logical puzzles about urns with balls. In the urn staying in front of Megabrain there are a red balls, b green balls and also c balls, colors of which are unknown to Megabrain. The occupiers demand an answer to a question: what is the maximal number of balls one can take out of this urn, so that there would be no more than n red and no more than m green balls among them for sure?

Input

The first line contains three integers ab and c separated by a space (0 ≤ a, b, c ≤ 109) — the number of red balls in the urn, the number of green balls in the urn, and the number of balls of unknown color in the urn, correspondingly.

The second line contains two integers n and m separated by a space (0 ≤ n, m ≤ 109) — the maximal number of red balls allowed to be taken out of the urn and the maximal number of green balls allowed to be taken out of the urn, correspondingly.

Output

Output a single integer — the maximal number of balls that can be taken out of the urn so that no restrictions are violated.


这题按照因为有一种球颜色不明,按照最坏的情况来考虑,即都是
红色或都是绿色,然后这两种情况根据球的个数不同再分七种情况
即可。
代码:

#include<cstdio>
#include<algorithm>
#include<string.h>
using namespace std;
int main()
{
    long long a,b,c,n,m;
    while(~scanf("%lld%lld%lld",&a,&b,&c))
    {
        scanf("%lld%lld",&n,&m);
        long long t1,t2;
        if(a+c<=n&&b<=m)t1=a+b+c;
        else if(n>=m)
        {
            if(a+c<=n&&b>m)
                t1=m;
            else if(a+c>n&&b>m)
                t1=m;
            else if(a+c>n&&b<=m)
                t1=n;
        }
        else
        {
            if(a+c<=n&&b>m)
                t1=m;
            else if(a+c>n&&b>m)
                t1=n;
            else if(a+c>n&&b<=m)
                t1=n;
        }
        if(a<=n&&b+c<=m)t2=a+b+c;
        else if(n>=m)
        {
            if(a<=n&&b+c>m)t2=m;
            else if(a>n&&b+c>m)t2=m;
            else if(a>n&&b+c<=m)t2=n;
        }
        else
        {
            if(a<=n&&b+c>m)t2=m;
            else if(a>n&&b+c>m)t2=n;
            else if(a>n&&b+c<=m)t2=n;
        }
        printf("%lld\n",min(t1,t2));
    }
    return 0;
}

D. Jumps
time limit per test
2.0 s
memory limit per test
256 MB
input
standard input
output
standard output

A frog lives in a one-dimensional world in the point with the coordinate 0. He needs to get to the point with the coordinate x. For some reason he cannot make jumps of arbitrary length, and can jump only by a1, ..., an in any direction. Is he able to reach x?

Input

The first line contains two integers n and x separated by a space (1 ≤ n ≤ 200000 - 109 ≤ x ≤ 109) — the number of variants of jump length and the coordinate of the point to reach.

The second line contains n integers ai separated by spaces (1 ≤ ai ≤ 109) — the lengths of jumps the frog can make.

Output

Output «YES» (without quotes), if the frog can reach the point x, otherwise output «NO» (without quotes).


两个数的最大公约数便是两个数加上一定系数所能得到的除0之外
的最小差,即所能分割的最小步数,所有数的gcd便是所有步数
所能凑出的最小分割步数。
代码:

#include<bits/stdc++.h>
using namespace std;
int gcd(int a,int b)
{
    return b==0?a:gcd(b,a%b);
}
int main()
{
    int n,x;scanf("%d%d",&n,&x);
    int i,j,k;scanf("%d",&k);
    for(i=2;i<=n;i++)
    {
        int y;scanf("%d",&y);
        k=gcd(k,y);
    }
    if(abs(x)%k)printf("NO\n");
    else printf("YES\n");
    return 0;
}

G. I love Codeforces
time limit per test
2.0 s
memory limit per test
256 MB
input
standard input
output
standard output

Among participants of programming contests at codeforces.com the following tradition is common: whenever a participant falls in love with another participant, he changes his nickname to «I_love_<nickname of the participant he fell in love with>». Unfortunately, for technical reasons site administration has lost the current nicknames of participants who had changed their nicknames recently, but the information about who of them fell in love with whom remains. Now the administration needs to write a program for determining the current nickname of the given participant. It should be noted that due to the small bug in the database structure different participants can have the same nicknames on this site.

Input

The first line contains a single integer n (2 ≤ n ≤ 200000) — the number of participants.

In the next n lines initial nicknames of participants are given. Each nickname is a non-empty string of length at most 24 characters, consisting only of uppercase and lowercase Latin letters and also underscores. Some nicknames can coincide.

The next line contains a single integer m (1 ≤ m ≤ 200000) — the number of records that one of the participants fell in love with another participant.

In the next m lines pairs of integers aj and bj, separated by a space, are given (1 ≤ aj, bj ≤ naj ≠ bj) — a record that the aj-th participant fell in love with the bj-th participant and changed his nickname correspondingly. Participants are numbered from one in the order their initial nicknames are given. Renamings occur in the order they are given.

Output

In the only line output the final nickname of the first participant after all renamings.


之前的状态会影响之后的状态,但是后来的状态不会影响到之前的
状态,倒过来跑一边即可。
代码:

#include<bits/stdc++.h>
int a[200004],b[200004];
char t[200004][27];
using namespace std;
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        int i,j,K;
        for(i=1;i<=n;i++)
            scanf("%s",t[i]);
        scanf("%d",&K);
        for(i=1;i<=K;i++)
            scanf("%d%d",&a[i],&b[i]);
            int T=1;
        for(i=K;i>=1;i--)
        {
            if(a[i]==T)
            {
                T=b[i];
                printf("I_love_");
            }
        }
        printf("%s\n",t[T]);
    }
    return 0;
}

H. Perfect Ban
time limit per test
2.0 s
memory limit per test
256 MB
input
standard input
output
standard output

Constantine and Mike are playing the board game «Wrath of Elves». There are n races and m classes of characters in this game. Each character is described by his race and class. For each race and each class there is exactly one character of this race and this class. The power of the character of the i-th race and the j-th class equals to aij, and both players know it perfectly.

Now Constantine will choose a character for himself. Before that Mike can ban one race and one class so that Constantine would not be able to choose characters of this race or of this class. Of course, Mike does his best to leave Constantine the weakest possible character, while Constantine, on the contrary, chooses the strongest character. Which race and class Mike should ban?

Input

The first line contains two integers n and m (2 ≤ n, m ≤ 1000) separated by a space — the number of races and classes in the game «Wrath of Elves», correspondingly.

The next n lines contain m integers each, separated by a space. The j-th number in the i-th of these lines is aij (1 ≤ aij ≤ 109).

Output

In the only line output two integers separated by a space — the number of race and the number of class Mike should ban. Races and classes are numbered from one. If there are several possible answers, output any of them.


找到最大值,最大值所在的行和列至少删除一个,删除行,此行都标记为
0,在找最优的列标记为零,然后寻找剩下的最大值,在删除列找最优的
行,都标记为0后找最大值,比较两个最大值即可。
代码:

#include<bits/stdc++.h>
using namespace std;
int t[1002][1002],a[1002],n,m;

int app(int x,int y)
{
    int ans=0;
    for(int i=1; i<=n; i++)
        for(int j=1; j<=m; j++)
        {
            if(i==x||j==y)continue;
            ans=max(ans,t[i][j]);
        }
    return ans;
}
int main()
{
    scanf("%d%d",&n,&m);
    int ma=0,x,y,x1,y1;
    for(int i=1; i<=n; i++)
        for(int j=1; j<=m; j++)
        {
            scanf("%d",&t[i][j]);
            if(t[i][j]>ma)
                ma=t[i][j],x=i,y=j;
        }
    for(int i=1; i<=m; i++)
        a[i]=t[x][i],t[x][i]=0;
    ma=0;
    for(int i=1; i<=m; i++)
    {
        for(int j=1; j<=n; j++)
        {
            if(t[j][i]>ma)
                ma=t[j][i],y1=i;
        }
    }
    int ans=app(x,y1);
    for(int i=1; i<=m; i++)
        t[x][i]=a[i];
    for(int i=1; i<=n; i++)
        a[i]=t[i][y],t[i][y]=0;
    ma=0;
    for(int i=1; i<=n; i++)
        for(int j=1; j<=m; j++)
        {
            if(t[i][j]>ma)
                ma=t[i][j],x1=i;
        }
    if(ans>app(x1,y))
        printf("%d %d\n",x1,y);
    else
        printf("%d %d\n",x,y1);
    return 0;
}

K. Competitions
time limit per test
2.0 s
memory limit per test
256 MB
input
standard input
output
standard output

Max is preparing hard for the most important event in his life — the ACM ICPC finals. He knows that in the nearest future n programming competitions are going to be held, and that the i-th of them starts at the moment of time ai, ends at the moment of time bi and has usefulness ci. To prepare better, he wants to choose for participating such set of competitions that their total usefulness will be as large as possible, and in case of a tie — that their total duration will be as small as possible. Of course, Max cannot participate in several competitions simultaneously, and also never starts competition after its moment of start and never gives up a competition before its end.

Input

The first line contains a single integer n (1 ≤ n ≤ 200000) — the number of competitions.

The next n lines contain three integers each aibici separated by a space (0 ≤ ai < bi ≤ 1091 ≤ ci ≤ 109) — times of the start and the end of the i-th competition and its usefulness.

Output

In the first line output three integers — the number of competitions k, in which Max should participate, and then their total usefulness and total duration.

In the second line output k integers separated by a space — the numbers of competitions Max should participate in. Competitions are numbered from one in the order they are listed in the input.

If there are several correct answers, output any of them.


根据结束时间升序排列,记录到每个结束时间的最优结果,每到一场
比赛时,二分找到最后一个结束时间在该场比赛开始之前的比赛
代码:

#include<cstdio>
#include<algorithm>
#include<string.h>
#include<vector>
using namespace std;
const int maxn = 200005;
int n,num[maxn],per[maxn],dec[maxn];
long long time[maxn], dp[maxn],end1[maxn];
struct node
{
	long long a, b, c;
	int dec;
}t[maxn];
bool cmp(const node& a, const node& b)
{
	if (a.b != b.b)return a.b < b.b;
	return a.a > b.b;
}
vector<int>p;
int main()
{
	while (~scanf("%d", &n))
	{
		int i, j;
		for (i = 1; i <= n; i++)
		{
			scanf("%lld%lld%lld", &t[i].a, &t[i].b, &t[i].c);
			t[i].dec = i;
		}
		sort(t + 1, t + n + 1, cmp);
		end1[0] = 0;
		for (i = 1; i <= n; i++)
			end1[i] = t[i].b;
		memset(time, 0, sizeof(time));
		memset(dp, 0, sizeof(dp));
		memset(num, 0, sizeof(num));
		memset(per, -1, sizeof(per));
		dec[0] = -1;
		long long Ktim, Ksorce = 0;
		int K, nn;
		for (i = 1; i <= n; i++)
		{
			int r = upper_bound(end1, end1 + n + 1, t[i].a) - end1 - 1;
			//printf("%d\n", r);
			long long tim, sorce;
			sorce = dp[r] + t[i].c;
			tim = time[r] + t[i].b - t[i].a;
			if (sorce > dp[i - 1] || (sorce == dp[i - 1] && tim < time[i - 1]))
			{
				dp[i] = sorce;
				time[i] = tim;
				num[i] = num[r] + 1;
				dec[i] = i;
			}
			else
			{
				dp[i] = dp[i - 1];
				time[i] = time[i - 1];
				num[i] = num[i - 1];
				dec[i] = dec[i - 1];
			}
			if(i!=1)per[i] = dec[r];//?//
			if (dp[i] > Ksorce || (dp[i] == Ksorce && Ktim > time[i]))
				Ksorce = dp[i], Ktim = time[i], K = i, nn = num[i];
		}
		while (K != -1)
		{
			p.push_back(K);
			K = per[K];
		}
		for (i = 0; i < p.size(); i++)
			p[i] = t[p[i]].dec;
		sort(p.begin(), p.end());
		printf("%d %lld %lld\n", nn, Ksorce, Ktim);
		for (i = 0; i < p.size() - 1; i++)
			printf("%d ", p[i]);
		printf("%d\n", p[p.size() - 1]);
		p.clear();
	}
	return 0;
}

M. Last Man Standing
time limit per test
2.0 s
memory limit per test
256 MB
input
standard input
output
standard output

A company of n friends decided to play a multiplayer shooter in the Last Man Standing mode. The distinctive feature of this mode is when a player is killed, he does not respawn, but waits a round to finish. A round finishes when there is only one player alive.

You are given a notarized screenshot of the current fight results, made during the first round of the game. It provides an information about how many kills each player has made. You want to check if it's a fake or not, i.e. whether such situation could occur during the game.

Input

The first line contains a single integer n (1 ≤ n ≤ 200000) — the number of players.

The second line contains n integers ai separated by a space (0 ≤ ai ≤ 109) — the numbers of kills made by each player. These numbers are given in non-increasing order.

Output

If such situation was not possible in the game, output «NO» (without quotes).

Otherwise, in the first line output «YES» (without quotes), and then output a log of kills in the round, consisting of k pairs of integers, where k is the total number of kills made at the moment of taking the screenshot. Each pair of integers in the log must consist of the number of the player who made the kill, and the number of the killed player, exactly in this order. Records in the log must be ordered chronologically. If there are several correct logs, output any of them.

Examples


#include<cstdio>
#include<queue>
using namespace std;
int a[200005],n,k[200005][2];
queue<int>P;
int main()
{
	while (~scanf("%d", &n))
	{
		int i, j;
		for (i = 1; i <= n; i++)
			scanf("%d", &a[i]);
		int L = 0;
		for (i = n; i >= 1; i--)
		{
			int r = a[i];
			while (r)
			{
				if (!P.empty())
				{
					k[L][0] = i;
					k[L++][1] = P.front();
					P.pop();
					r--;
				}
				else
				{
					printf("NO\n");
					return 0;
				}
			}
			P.push(i);
		}
		printf("YES\n");
		for (i = 0; i < L; i++)
			printf("%d %d\n", k[i][0], k[i][1]);
		while (!P.empty())P.pop();
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值