Educational Codeforces Round 85 (Rated for Div. 2) [A-D]

http://www.yyycode.cn/index.php/2020/04/18/educational-codeforces-round-85-rated-for-div-2a-d/


A. Level Statisticstime

limit per test2 secondsmemory limit per test256 megabytesinputstandard inputoutputstandard output

Polycarp has recently created a new level in this cool new game Berlio Maker 85 and uploaded it online. Now players from all over the world can try his level.

All levels in this game have two stats to them: the number of plays and the number of clears. So when a player attempts the level, the number of plays increases by 11. If he manages to finish the level successfully then the number of clears increases by 11 as well. Note that both of the statistics update at the same time (so if the player finishes the level successfully then the number of plays will increase at the same time as the number of clears).

Polycarp is very excited about his level, so he keeps peeking at the stats to know how hard his level turns out to be.

So he peeked at the stats nn times and wrote down nn pairs of integers — (p1,c1),(p2,c2),…,(pn,cn)(p1,c1),(p2,c2),…,(pn,cn), where pipi is the number of plays at the ii-th moment of time and cici is the number of clears at the same moment of time. The stats are given in chronological order (i.e. the order of given pairs is exactly the same as Polycarp has written down).

Between two consecutive moments of time Polycarp peeked at the stats many players (but possibly zero) could attempt the level.

Finally, Polycarp wonders if he hasn’t messed up any records and all the pairs are correct. If there could exist such a sequence of plays (and clears, respectively) that the stats were exactly as Polycarp has written down, then he considers his records correct.

Help him to check the correctness of his records.

For your convenience you have to answer multiple independent test cases.Input

The first line contains a single integer TT (1≤T≤500)(1≤T≤500) — the number of test cases.

The first line of each test case contains a single integer nn (1≤n≤1001≤n≤100) — the number of moments of time Polycarp peeked at the stats.

Each of the next nn lines contains two integers pipi and cici (0≤pi,ci≤10000≤pi,ci≤1000) — the number of plays and the number of clears of the level at the ii-th moment of time.

Note that the stats are given in chronological order.Output

For each test case print a single line.

If there could exist such a sequence of plays (and clears, respectively) that the stats were exactly as Polycarp has written down, then print “YES”.

Otherwise, print “NO”.

You can print each letter in any case (upper or lower).ExampleinputCopy

6
3
0 0
1 1
1 2
2
1 0
1000 3
4
10 1
15 2
10 2
15 2
1
765 432
2
4 4
4 3
5
0 0
1 0
1 0
1 0
1 0

outputCopy

NO
YES
NO
YES
NO
YES

Note

In the first test case at the third moment of time the number of clears increased but the number of plays did not, that couldn’t have happened.

The second test case is a nice example of a Super Expert level.

In the third test case the number of plays decreased, which is impossible.

The fourth test case is probably an auto level with a single jump over the spike.

In the fifth test case the number of clears decreased, which is also impossible.

Nobody wanted to play the sixth test case; Polycarp’s mom attempted it to make him feel better, however, she couldn’t clear it.


看懂题意的话就很好做了,false的四个条件:a[i]<a[i-1],b[i]<b[i-1],a[i-1]<b[i-1],a[i]-a[i-1]<b[i]-b[i-1].

自己理解题意错了,以为是一串数据中要标记最值


#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=1e2+10;
int a[maxn],b[maxn];
int main(void)
{
	int t;cin>>t;
	while(t--)
	{
		int n;cin>>n;
		int flag=1;
		for(int i=1;i<=n;i++)
			{
				cin>>a[i]>>b[i];
 
				if(a[i]<a[i-1]||b[i]<b[i-1]||a[i]<b[i]||a[i]-a[i-1]<b[i]-b[i-1])
				{
					flag=0;
				}	
			}
		if(flag)
			cout<<"YES"<<endl;
		else if(!flag)
			cout<<"NO"<<endl;
	}
return 0;
}

B. Middle Class

Many years ago Berland was a small country where only nn people lived. Each person had some savings: the ii-th one had aiai burles.

The government considered a person as wealthy if he had at least xx burles. To increase the number of wealthy people Berland decided to carry out several reforms. Each reform looked like that:

  • the government chooses some subset of people (maybe all of them);
  • the government takes all savings from the chosen people and redistributes the savings among the chosen people equally.

For example, consider the savings as list [5,1,2,1][5,1,2,1]: if the government chose the 11-st and the 33-rd persons then it, at first, will take all 5+2=75+2=7 burles and after that will return 3.53.5 burles to the chosen people. As a result, the savings will become [3.5,1,3.5,1][3.5,1,3.5,1].

A lot of data was lost from that time, so we don’t know how many reforms were implemented and to whom. All we can do is ask you to calculate the maximum possible number of wealthy people after several (maybe zero) reforms.Input

The first line contains single integer TT (1≤T≤10001≤T≤1000) — the number of test cases.

Next 2T2T lines contain the test cases — two lines per test case. The first line contains two integers nn and xx (1≤n≤1051≤n≤105, 1≤x≤1091≤x≤109) — the number of people and the minimum amount of money to be considered as wealthy.

The second line contains nn integers a1,a2,…,ana1,a2,…,an (1≤ai≤1091≤ai≤109) — the initial savings of each person.

It’s guaranteed that the total sum of nn doesn’t exceed 105105.Output

Print TT integers — one per test case. For each test case print the maximum possible number of wealthy people after several (maybe zero) reforms.ExampleinputCopy

4
4 3
5 1 2 1
4 10
11 9 11 9
2 5
4 3
3 7
9 4 9

outputCopy

2
4
0
3

Note

The first test case is described in the statement.

In the second test case, the government, for example, could carry out two reforms: [11–––,9–,11,9]→[10,10,11–––,9–]→[10,10,10,10][11_,9_,11,9]→[10,10,11_,9_]→[10,10,10,10].

In the third test case, the government couldn’t make even one person wealthy.

In the fourth test case, the government could choose all people to carry out a reform: [9–,4–,9–]→[713,713,713][9_,4_,9_]→[713,713,713].


怎么wp复制题面总是会出问题?


题意:给一串序列和一个标准值,可以有将几个人的财富收集再将这几个人的财富平均分给上交的这几个人,问最多过小康线的能有多少人

思路:

  • 要求一段连续序列的和(此题数据大)容易往前缀和上去联想
  • 怎么让其连续并且求出的是最多的人数,大到小sort,使其变连续,然后sum[i]/i判断低于标准就break。[前面的人钱多,而人的增量是1,这样能最大化达到小康线的标准]
  • 代码上注意要开LL,不然WA在test4.
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
int const N=1e5+10;
LL sum[N];
LL a[N];
bool cmp(LL a,LL b)
{
	return a>b;
}
int main(void)
{
	LL t;cin>>t;
	while(t--)
	{
		LL n;cin>>n;
		LL x;cin>>x;
		memset(a,0,sizeof(a));
		memset(sum,0,sizeof(sum));
		for(LL i=1;i<=n;i++) 
		{
			cin>>a[i];
		}
		sort(a+1,a+n+1,cmp);
		for(LL i=1;i<=n;i++)
		{
			sum[i]=sum[i-1]+a[i];
		}
		int flag=1;
		for(LL i=1;i<=n;i++)
		{
			double k=sum[i]/i;
			if(k<x)
				{
					cout<<i-1<<endl;flag=0;break;
				}		
		}
		if(flag)
			cout<<n<<endl;
	}
return 0;
}

C. Circle of Monsters

You are playing another computer game, and now you have to slay nn monsters. These monsters are standing in a circle, numbered clockwise from 11 to nn. Initially, the ii-th monster has aiai health.

You may shoot the monsters to kill them. Each shot requires exactly one bullet and decreases the health of the targeted monster by 11 (deals 11 damage to it). Furthermore, when the health of some monster ii becomes 00 or less than 00, it dies and explodes, dealing bibi damage to the next monster (monster i+1i+1, if i<ni<n, or monster 11, if i=ni=n). If the next monster is already dead, then nothing happens. If the explosion kills the next monster, it explodes too, damaging the monster after it and possibly triggering another explosion, and so on.

You have to calculate the minimum number of bullets you have to fire to kill all nn monsters in the circle.Input

The first line contains one integer TT (1≤T≤1500001≤T≤150000) — the number of test cases.

Then the test cases follow, each test case begins with a line containing one integer nn (2≤n≤3000002≤n≤300000) — the number of monsters. Then nn lines follow, each containing two integers aiai and bibi (1≤ai,bi≤10121≤ai,bi≤1012) — the parameters of the ii-th monster in the circle.

It is guaranteed that the total number of monsters in all test cases does not exceed 300000.Output

For each test case, print one integer — the minimum number of bullets you have to fire to kill all of the monsters.ExampleinputCopy

1
3
7 15
2 14
5 3

outputCopy

6

题意:一堆怪物围成一个环,每个怪物有血量值a[i]和爆炸伤害值b[i],同时要注意题意是怪物爆炸只对下标为下一个的怪兽有爆炸伤害。特别的,环的交界处是最后一个对第一个有爆炸伤害。

自己做题的时候以为是两边都有伤害,想了半天


思路:

  • 杀死任意一个怪物,下一个怪物的需要的额外子弹数为max(0,a[i]-b[i-1]);
  • 从第一个怪兽开始,计算每个怪物需要的额外子弹的 总和SUM。
  • 然后我们枚举一个特定的怪兽,那么该怪兽的额外子弹不用考虑,因为先前的怪兽没有爆炸(并且爆炸了这个特定怪兽是最先死的,爆炸了对它没有伤害)。
  • 于是要发射与该怪物的生命相同数量的子弹。那么枚举这个怪物消灭全体怪物需要的子弹数目是:使用(SUM-(该怪物的额外子弹)+(该怪物的生命值))【因为真实的要用的子弹数是所有怪物的额外SUM加上消灭这个枚举怪物的子弹数—枚举怪物的额外子弹(因为它最早死)】
  • 没必要每次memset,因为a[],b[]都用到当前输入的n即可,并且每次都会被覆盖重新输入。用了反而超时
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long LL;
const int N=300010;
LL A[N],B[N],v[N];

int main(void)
{
	LL t;
	scanf("%lld",&t);
	while(t--)
	{
	//memset(A,0,sizeof(A));memset(B,0,sizeof(B));memset(v,0,sizeof(v));
		LL n;scanf("%lld",&n);
		for(LL i=0;i<n;i++)
			{
				scanf("%lld%lld",&A[i],&B[i]);
			}
		LL sum=0;
		for(LL i=0;i<n;i++)
		{
			if(!i)
			{
				v[i]=max((LL)0,A[0]-B[n-1]);
			}
			else 
			{
				v[i]=max((LL)0,A[i]-B[i-1]);
			}
			sum+=v[i];
		}
		LL nmin=sum-v[0]+A[0];
		for(int i=1;i<n;i++)
		{
			nmin=min(nmin,sum-v[i]+A[i]);
		}
		printf("%lld\n",nmin);
	}
return 0;	
}

D. Minimum Euler Cycle

You are given a complete directed graph KnKn with nn vertices: each pair of vertices u≠vu≠v in KnKn have both directed edges (u,v)(u,v) and (v,u)(v,u); there are no self-loops.

You should find such a cycle in KnKn that visits every directed edge exactly once (allowing for revisiting vertices).

We can write such cycle as a list of n(n−1)+1n(n−1)+1 vertices v1,v2,v3,…,vn(n−1)−1,vn(n−1),vn(n−1)+1=v1v1,v2,v3,…,vn(n−1)−1,vn(n−1),vn(n−1)+1=v1 — a visiting order, where each (vi,vi+1)(vi,vi+1) occurs exactly once.

Find the lexicographically smallest such cycle. It’s not hard to prove that the cycle always exists.

Since the answer can be too large print its [l,r][l,r] segment, in other words, vl,vl+1,…,vrvl,vl+1,…,vr.Input

The first line contains the single integer TT (1≤T≤1001≤T≤100) — the number of test cases.

Next TT lines contain test cases — one per line. The first and only line of each test case contains three integers nn, ll and rr (2≤n≤1052≤n≤105, 1≤l≤r≤n(n−1)+11≤l≤r≤n(n−1)+1, r−l+1≤105r−l+1≤105) — the number of vertices in KnKn, and segment of the cycle to print.

It’s guaranteed that the total sum of nn doesn’t exceed 105105 and the total sum of r−l+1r−l+1 doesn’t exceed 105105.Output

For each test case print the segment vl,vl+1,…,vrvl,vl+1,…,vr of the lexicographically smallest cycle that visits every edge exactly once.ExampleinputCopy

3
2 1 3
3 3 6
99995 9998900031 9998900031

outputCopy

1 2 1 
1 3 2 3 
1 

Note

In the second test case, the lexicographically minimum cycle looks like: 1,2,1,3,2,3,11,2,1,3,2,3,1.

In the third test case, it’s quite obvious that the cycle should start and end in vertex 11.


题意:给定一个有向图,并且顶点之间是双向可走,要求点可以重复到,但是每每条路只能走一次。求字典序最小的走法,同时因为这个太多了所以求里面的某一个区间。

前置知识点:

  • 欧拉路就是那种一笔连通问题
  • 图先要是连通图才能判断,一个点上连接的边的数量称为这个点的度,在无向图中,如果度数是奇数,这个点称为奇点,如果度数是偶数,则称为偶点。
  • 无向连通图的判断条件:如果图中的点都是偶点,则存在欧拉回路;任意一个点都可以作为起点和终点。如果只有两个奇点,则存在欧拉路,其中一个是起点,另一个是终点
  • 有向连通图的判断条件:一个点的出度记1,入度记-1,这点的所有出度和入读相加就是这个点的度数。一个有向图存在欧拉回路,当且仅当所有点的度数为0。如果只有一个度数为1的点,一个度数-1的点,其他都为0,那么该欧拉路径的起点为度数1的点,终点为-1的度数的点.

那么回到这个题:每个点都有对应的入度和出度并且和都为0,则一定存在欧拉回路。

题目说字典序最小,那么1->2->1->3肯定小于1->2>3于是就尽量往回走

举个n=5; 那么就会有1->2->1->3->1->4->1->5; (可以认为是端点为1的)

那么下一种是2->3->2->4->2->5.最后一定能回到1,总数是n*(n-1)+1;

出现这种形式很像之前一场div2的B题构造。

然后就是发现规律的过程


总结一下:发现规律的构造可以用sum[i]表示起点在某一类的数目,然后用前缀和累加sum[i+1],sum[i+2].给个点找里面对应位置在哪的时候,可以(看数据)用二分找在哪个sum[x],然后减去sum[x-1]就可以得到该点在sum[x]的相对标号(就是从该序列的1,2,3..开始),然后去找之间的下标奇偶性发现规律求解


#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N=1e5+100;
LL n;
LL sum[N];
int fabs(LL pos)
{
	if(pos==n*(n-1)+1) return 1;
	/*
	for(LL i=1;i<=n;i++)
	{
		if(sum[i]>=pos) 
		{
			j=i;break; 
		}
	}
	*/
	int l=1;int r=n;
	while(l<r)
	{
		int mid=(l+r)/2;
		if(sum[mid]>=pos) r=mid;
		else l=mid+1;
	}
	LL j=l;
	LL b=pos-sum[j-1];
	if(b&1) return j;
	else return j+b/2;
}

int main(void)
{
	int t;scanf("%d",&t);
	while(t--)
	{
		LL l,r;
		scanf("%lld%lld%lld",&n,&l,&r);
		for(int i=1;i<=n;i++)
			sum[i]=sum[i-1]+2*(n-i);
		for(LL i=l;i<=r;i++)
			printf("%d ",fabs(i));
		printf("\n");		
	}
return 0;	 
}

猜你喜欢

转载自blog.csdn.net/zstuyyyyccccbbbb/article/details/105595502