【codeforces #278(div 1)】ABCD题解

A. Fight the Monster

time limit per test

1 second

memory limit per test

256 megabytes

input

standard input

output

standard output

A monster is attacking the Cyberland!

Master Yang, a braver, is going to beat the monster. Yang and the monster each have 3 attributes: hitpoints (HP), offensive power (ATK)
and defensive power (DEF).

During the battle, every second the monster‘s HP decrease by max(0,?ATKY?-?DEFM),
while Yang‘s HP decreases bymax(0,?ATKM?-?DEFY),
where index Y denotes Master Yang and index M denotes
monster. Both decreases happen simultaneously Once monster‘s HP?≤?0 and the same time Master Yang‘s HP?>?0,
Master Yang wins.

Master Yang can buy attributes from the magic shop of Cyberland: h bitcoins per HPa bitcoins
per ATK, and d bitcoins per DEF.

Now Master Yang wants to know the minimum number of bitcoins he can spend in order to win.

Input

The first line contains three integers HPY,?ATKY,?DEFY,
separated by a space, denoting the initial HPATK and DEF of
Master Yang.

The second line contains three integers HPM,?ATKM,?DEFM,
separated by a space, denoting the HPATK and DEF of
the monster.

The third line contains three integers h,?a,?d, separated by a space, denoting the price of 1 HP, 1 ATK and 1 DEF.

All numbers in input are integer and lie between 1 and 100 inclusively.

Output

The only output line should contain an integer, denoting the minimum bitcoins Master Yang should spend in order to win.

Sample test(s)

input

1 2 1
1 100 1
1 100 100

output

99

input

100 100 100
1 1 1
1 1 1

output

0

Note

For the first sample, prices for ATK and DEF are
extremely high. Master Yang can buy 99 HP, then he can beat the monster with 1HP
left.

For the second sample, Master Yang is strong enough to beat the monster, so he doesn‘t need to buy anything.

暴力。

h2:每秒减少max(0,a1-d2)

h1:每秒减少max(0,a2-d1)

要求让h1比h2先减完。

先考虑一种特殊情况:

如果两人都是每秒减少0,那么此时增加a1,d1都是起反作用的,只能增加h1。

其他情况下,d1最多增加到a2(再大没有意义),a1最多增加到d2+h1(再大没有意义)。

那么我们枚举d1,a1的增加量(O(n^2)  n=100),可以O(1)算出来要获胜h1增加多少(代码中这里也是枚举的。。),最后输出最小费用即可。

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <cstdlib>
using namespace std;
int h1,h2,a1,a2,d1,d2,hc,dc,ac;
int win(int h1,int h2,int a1,int d1,int a2,int d2)
{
	int x1=max(0,a2-d1),x2=max(0,a1-d2);
	if (x1==0&&x2!=0) return 1;
	if (x2==0) return 0;
	int k1=ceil((double)h1/x1),k2=ceil((double)h2/x2);
	if (k1>k2) return 1;
	return 0;
}
int main()
{
        cin>>h1>>a1>>d1;
	cin>>h2>>a2>>d2;
	cin>>hc>>ac>>dc;
	int ans=1000000;
	if (win(h1,h2,a1,d1,a2,d2))
	{
		cout<<0<<endl;
		return 0;
	}
	int k;
	if (max(a2-d1,0)==0)
	{
		cout<<(d2+1-a1)*ac<<endl;
		return 0;
	}
	k=ceil((double)h1/(a2-d1));
	for (int d=0;d<=a2;d++)
		for (int a=0;a<=200;a++)
		{
			if (win(h1,h2,a1+a,d1+d,a2,d2))
			{
				ans=min(ans,a*ac+d*dc);
				continue;
			}
			for (int i=k+1;i<=100;i++)
			{
				int h=(i-1)*(a2-d1)+1-h1;
				if (win(h1+h,h2,a1+a,d1+d,a2,d2))
				{
					ans=min(ans,h*hc+a*ac+d*dc);
					continue;
				}
			}
		}
	cout<<ans<<endl;
	return 0;
}

B. Strip

time limit per test

1 second

memory limit per test

256 megabytes

input

standard input

output

standard output

Alexandra has a paper strip with n numbers on it. Let‘s call them ai from
left to right.

Now Alexandra wants to split it into some pieces (possibly 1). For each piece of strip, it must satisfy:

  • Each piece should contain at least l numbers.
  • The difference between the maximal and the minimal number on the piece should be at most s.

Please help Alexandra to find the minimal number of pieces meeting the condition above.

Input

The first line contains three space-separated integers n,?s,?l (1?≤?n?≤?105,?0?≤?s?≤?109,?1?≤?l?≤?105).

The second line contains n integers ai separated
by spaces (?-?109?≤?ai?≤?109).

Output

Output the minimal number of strip pieces.

If there are no ways to split the strip, output -1.

Sample test(s)

input

7 2 2
1 3 1 2 4 1 2

output

3

input

7 2 2
1 100 1 100 1 100 1

output

-1

Note

For the first sample, we can split the strip into 3 pieces: [1,?3,?1],?[2,?4],?[1,?2].

For the second sample, we can‘t let 1 and 100 be on the same piece,
so no solution exists.

题解中的做法是单调队列:

使用一个单增队列和一个单减队列求出g[i],表示i可以由g[i]到i-l转移;

再用一个单增队列,求出f[i]表示前i个数最少分成f[i]段,f[i]=min(f[k]+1)  (g[i]<=k<=i-l)

其实也可以用set来做(虽然慢一点,但是好写多了):

两个set:

s放a[i],dp放f[i]

每次插入a[i],如果s中max-min>S,那么就把最靠前a[j]的弹出,把他对应的f[j-1]也弹出(如果被放入的话);

如果i-j+1>=l就把f[i-j]插入。

f[i]就是dp这个set中最小的元素+1

#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <algorithm>
#include <set>
#define mp make_pair
#define pa pair<int,int>
#define M 100000+5
#define inf 0x3f3f3f3f
using namespace std;
int f[M],n,ss,l,a[M];
multiset<int> s,dp;
int main()
{
        scanf("%d%d%d",&n,&ss,&l);
	for (int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	for (int i=1,j=1;i<=n;i++)
	{
		s.insert(a[i]);
		for (;*s.rbegin()-*s.begin()>ss;j++)
		{
			s.erase(s.find(a[j]));
			if (i-j>=l)
				dp.erase(dp.find(f[j-1]));
		}
	        if (i-j+1>=l) dp.insert(f[i-l]);
		if (dp.begin()==dp.end())
			f[i]=inf;
		else f[i]=*dp.begin()+1;
	}
	if (f[n]>=inf)
		puts("-1");
	else cout<<f[n]<<endl;
	return 0;
}

C. Prefix Product Sequence

time limit per test

1 second

memory limit per test

256 megabytes

input

standard input

output

standard output

Consider a sequence [a1,?a2,?...
,?an]. Define its prefix product sequence .

Now given n, find a permutation of [1,?2,?...,?n],
such that its prefix product sequence is a permutation of [0,?1,?...,?n?-?1].

Input

The only input line contains an integer n (1?≤?n?≤?105).

Output

In the first output line, print "YES" if such sequence exists, or print "NO"
if no such sequence exists.

If any solution exists, you should output n more lines. i-th
line contains only an integer ai.
The elements of the sequence should be different positive integers no larger than n.

If there are multiple solutions, you are allowed to print any of them.

Sample test(s)

input

7

output

YES
1
4
3
6
5
2
7

input

6

output

NO

Note

For the second sample, there are no valid sequences.

首先1肯定放第一个,n肯定放最后一个:

1放中间就和他前面的模值相同了;n放中间后面mod n全是0。

然后可以发现除了1,4和质数之外,答案都是NO,因为合数(n-1)! mod n=n,也就是说至少有两个mod n=0。

那么质数如何求方案数?

用这样的式子:

i=2

i/(i-1) * (i+1)/i * (i+2)/(i+1)...*(i+k)/(i+k-1)=i+k

第i位是i/(i-1),就可以得到一个排列了。

可以证明每一位的i/(i-1)都是不同的。

#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <algorithm>
using namespace std;
int n;
int ni(int x,int n,int mod)
{
	long long b=x,ans=1;
	while (n)
	{
		if (n&1) ans=ans*b%mod;
		b=b*b%mod;
		n>>=1;
	}
	return (int)(ans%mod);
}
int main()
{
	cin>>n;
	if (n==1)
	{
		printf("YES\n1\n");
		return 0;
	}
	if (n==4)
	{
		printf("YES\n1\n3\n2\n4\n");
		return 0;
	}
	for (int i=2;i<n;i++)
		if (n%i==0)
		{
			puts("NO");
			return 0;
		}
	printf("YES\n1\n");
	for (int i=2;i<n;i++)
		printf("%d\n",(int)(1LL*i*ni(i-1,n-2,n)%n));
	printf("%d\n",n);
	return 0;
}

D. Conveyor Belts

time limit per test

3 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

Automatic Bakery of Cyberland (ABC) recently bought an n?×?m rectangle table. To serve the diners, ABC placed seats around the table. The size
of each seat is equal to a unit square, so there are 2(n?+?m) seats in total.

ABC placed conveyor belts on each unit square on the table. There are three types of conveyor belts: "^", "<"
and ">". A "^" belt can bring
things upwards. "<" can bring leftwards and ">"
can bring rightwards.

Let‘s number the rows with 1 to n from top to bottom,
the columns with 1 to m from left to right. We consider
the seats above and below the top of the table are rows 0 and n?+?1 respectively.
Also we define seats to the left of the table and to the right of the table to be column 0 and m?+?1.
Due to the conveyor belts direction restriction there are currently no way for a diner sitting in the row n?+?1 to be served.

Given the initial table, there will be q events in order. There are two types of events:

  • "A x y" means, a piece of bread will appear at
    row x and column y (we will denote such position
    as (x,?y)). The bread will follow the conveyor belt, until arriving at a seat of a diner. It is possible that the bread gets stuck in an infinite
    loop. Your task is to simulate the process, and output the final position of the bread, or determine that there will be an infinite loop.
  • "C x y c"
    means that the type of the conveyor belt at (x,?y) is changed to c.

Queries are performed separately meaning that even if the bread got stuck in an infinite loop, it won‘t affect further queries.

Input

The first line of input contains three integers nm and q (1?≤?n?≤?105,?1?≤?m?≤?10,?1?≤?q?≤?105),
separated by a space.

Next n lines, each line contains m characters,
describing the table. The characters can only be one of "<^>".

Next q lines, each line describes an event. The format is "C
x y c" or "A x y" (Consecutive elements are separated by a space). It‘s guaranteed that 1?≤?x?≤?n,?1?≤?y?≤?mc is
a character from the set "<^>".

There are at most 10000 queries of "C" type.

Output

For each event of type "A", output two integers txty in
a line, separated by a space, denoting the destination of (x,?y) is (tx,?ty).

If there is an infinite loop, you should output tx?=?ty?=??-?1.

Sample test(s)

input

2 2 3
>>
^^
A 2 1
C 1 2 <
A 2 1

output

1 3
-1 -1

input

4 5 7
><<^<
^<^^>
>>>^>
>^>>^
A 3 1
A 2 2
C 1 4 <
A 3 1
C 1 2 ^
A 3 1
A 2 2

output

0 4
-1 -1
-1 -1
0 2
0 2

Note

For the first sample:

If the bread goes from (2,?1), it will go out of the table at (1,?3).

After changing the conveyor belt of (1,?2) to "<",
when the bread goes from (2,?1) again, it will get stuck at "><",
so output is (?-?1,??-?1).

分块/线段树。

分块很好写:

m很小,所以按照n分为sqrt(n)块,维护在每一块中能走到哪里,修改也只修改所在块。

注意修改的时候对于这一块的最上层要特判一下,因为上面那层也许还没更新。

因此每一个询问复杂度O(n/sqrt(n))=O(sqrt(n));

每一个修改复杂度O(m*sqrt(n))

线段树是按照n分段的,每个节点x维护tree[x][i]:表示从(r,i)能走到(l,tree[x][i]),l和r分别是左右子树,然后修改就是区间合并区间查询的问题了。

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#define mp make_pair
#define M 100000+5
using namespace std;
pair<int,int> f[M][20];
char s[M][20];
int z,n,m,q,num[M],cnt;
void Modify(int x1,int x2)
{
	for (int i=x1;i<=x2;i++)
	{
		for (int j=0;j<=m+1;j++)
			f[i][j]=mp(i,j);
		for (int j=1;j<=m;j++)
			if (s[i][j]=='^')
				f[i][j]=i==x1?mp(x1-1,j):f[i-1][j];
		for (int j=1;j<=m;j++)
			if (s[i][j]=='<')
				f[i][j]=f[i][j-1];
		for (int j=m;j;j--)
			if (s[i][j]=='>')
				f[i][j]=f[i][j+1];
	}
}
int main()
{
        scanf("%d%d%d",&n,&m,&q);
	for (int i=1;i<=m;i++)
		f[0][i]=mp(0,i);
	for (int i=1;i<=n;i++)
		scanf("%s",s[i]+1);
	z=sqrt(n)+1;
	cnt=-1;
	for (int i=1;i<=n;i+=z)
	{
		cnt++;
		Modify(i,min(n,i+z-1));
		for (int j=i;j<=min(n,i+z-1);j++)
			num[j]=cnt;
	}
	while (q--)
	{
		char t[5];
		int x,y;
		scanf("%s%d%d",t,&x,&y);
		if (t[0]=='A')
		{
			int xx=x,yy=y;
			int ok=1;
			while (xx>=1&&yy>=1&&yy<=m)
			{
			    int nx=f[xx][yy].first,ny=f[xx][yy].second;
	                    if (nx==xx&&ny>=1&&ny<=m)
			    {
					ok=0;
					puts("-1 -1");
					break;
			    }
			    xx=nx,yy=ny;
			}
			if (ok)
				printf("%d %d\n",xx,yy);
		}
		else
		{
			scanf("%s",t);
			int fi=num[x]*z+1;
			s[x][y]=t[0];
			Modify(x,min(fi+z-1,n));
		}
	}
	return 0;
}

感悟:

看来我线段树还是没学好,D有时间写一下。。

时间: 2024-08-18 00:25:24

【codeforces #278(div 1)】ABCD题解的相关文章

Codeforces Round #250 (Div. 2) (ABCD题解)

比赛链接:http://codeforces.com/contest/433 A. Kitahara Haruki's Gift time limit per test:1 second memory limit per test:256 megabytes Kitahara Haruki has bought n apples for Touma Kazusa and Ogiso Setsuna. Now he wants to divide all the apples between th

Codeforces Round #Pi (Div. 2) (ABCD题解)

比赛链接:http://codeforces.com/contest/567 听说Round #Pi的意思是Round #314... A. Lineland Mail time limit per test:3 seconds memory limit per test:256 megabytes All cities of Lineland are located on the Ox coordinate axis. Thus, each city is associated with it

Codeforces Round #249 (Div. 2) (ABCD题解)

比赛链接:http://codeforces.com/contest/435 A. Queue on Bus Stop time limit per test:1 second memory limit per test:256 megabytes It's that time of the year when the Russians flood their countryside summer cottages (dachas) and the bus stop has a lot of p

Codeforces Round #313 (Div. 2) (ABCD题解)

比赛链接:http://codeforces.com/contest/560 水笔场... A. Currency System in Geraldion time limit per test:2 seconds memory limit per test:256 megabytes A magic island Geraldion, where Gerald lives, has its own currency system. It uses banknotes of several va

Codeforces Round #302 (Div. 2) (ABCD题解)

比赛链接:http://codeforces.com/contest/544 A. Set of Strings time limit per test:1 second memory limit per test:256 megabytes You are given a string q. A sequence of k strings s1,?s2,?...,?sk is called beautiful, if the concatenation of these strings is

Codeforces Round #533 (Div. 2) ABCD 题解

题目链接 A. Salem and Sticks 分析 暴力就行,题目给的n<=1000,ai<=100,暴力枚举t,t从2枚举到98,复杂度是1e5,完全可行. 代码 1 #include <cstdio> 2 #include <cmath> 3 #include <iostream> 4 #include <cstring> 5 #include <algorithm> 6 #include <vector> 7 #

Codeforces Round #278 (Div. 2) b

/**  *  * @brief Codeforces Round #278 (Div. 2) b  * @file b.c  * @author mianma  * @created 2014/11/24 17:52  * @edited  2014/11/18 17:52  * @type brute  *   * @note   *          declare k >= 0;  *              then   *                  x1 = k  *   

Codeforces Round #278 (Div. 2) d

/**  * @brief Codeforces Round #278 (Div. 2) d  * @file d.c  * @author 面码  * @created 2014/11/26 10:07  * @edited  2014/11/26 10:07  * @type dp   * @note  *      自己的TL了,看了别人代码写的  *      该代码主要是在dp的基础上使用stl来提速  *      dp需辅助提速,但内存又不能爆掉是该题目的卡点 = =  */ #i

Codeforces Round #258 (Div. 2)[ABCD]

Codeforces Round #258 (Div. 2)[ABCD] ACM 题目地址:Codeforces Round #258 (Div. 2) A - Game With Sticks 题意: Akshat and Malvika两人玩一个游戏,横竖n,m根木棒排成#型,每次取走一个交点,交点相关的横竖两条木棒要去掉,Akshat先手,给出n,m问谁赢. 分析: 水题,很明显不管拿掉哪个点剩下的都是(n-1,m-1),最后状态是(0,x)或(x,0),也就是拿了min(n,m)-1次,