codeforces #700 Div.2

A. Yet Another String Game

Homer has two friends Alice and Bob. Both of them are string fans.

One day, Alice and Bob decide to play a game on a string s=s1s2…sn of length n consisting of lowercase English letters. They move in turns alternatively and Alice makes the first move.

In a move, a player must choose an index i (1≤i≤n) that has not been chosen before, and change si to any other lowercase English letter c that c≠si.

When all indices have been chosen, the game ends.

The goal of Alice is to make the final string lexicographically as small as possible, while the goal of Bob is to make the final string lexicographically as large as possible. Both of them are game experts, so they always play games optimally. Homer is not a game expert, so he wonders what the final string will be.

A string a is lexicographically smaller than a string b if and only if one of the following holds:

a is a prefix of b, but a≠b;
in the first position where a and b differ, the string a has a letter that appears earlier in the alphabet than the corresponding letter in b.
Input
Each test contains multiple test cases. The first line contains t (1≤t≤1000) — the number of test cases. Description of the test cases follows.

The only line of each test case contains a single string s (1≤|s|≤50) consisting of lowercase English letters.

Output
For each test case, print the final string in a single line.

Example
input

3
a
bbbb
az

output

b
azaz
by

Note
In the first test case: Alice makes the first move and must change the only letter to a different one, so she changes it to ‘b’.

In the second test case: Alice changes the first letter to ‘a’, then Bob changes the second letter to ‘z’, Alice changes the third letter to ‘a’ and then Bob changes the fourth letter to ‘z’.

In the third test case: Alice changes the first letter to ‘b’, and then Bob changes the second letter to ‘y’.

题目大意: 给定测试数据组数n,每组给出一串字符串,两个人轮流替换字符串的某个字符(不能重复且替换后的字符串不等于替换前的字符串),一人先手要字符串的字典序最小,一人后手要字符串的字典序最大,求最后的字符串。
解题思路: 水题。贪心处理,从第一个字符开始,轮流把字符变成‘a’(若字符为‘a’,则变成‘b’)和‘z’(若字符为‘z’,则变成‘y’)。
参考代码:

#include <iostream>
#include <stdio.h>

int main()
{
    int t;
    char str[55];
    scanf("%d",&t);
    while(t--)
    {
        scanf("%s",str);
        for(int i = 0;str[i] != '\0';i++)
        {
            if(i % 2 == 0)
            {
                str[i] = str[i] != 'a' ? 'a' : 'b';
            }
            else
            {
                str[i] = str[i] != 'z' ? 'z' : 'y'; 
            }
        }
        printf("%s\n",str);
    }
}

B. The Great Hero

The great hero guards the country where Homer lives. The hero has attack power A and initial health value B. There are n monsters in front of the hero. The i-th monster has attack power ai and initial health value bi.

The hero or a monster is said to be living, if his or its health value is positive (greater than or equal to 1); and he or it is said to be dead, if his or its health value is non-positive (less than or equal to 0).

In order to protect people in the country, the hero will fight with monsters until either the hero is dead or all the monsters are dead.

In each fight, the hero can select an arbitrary living monster and fight with it. Suppose the i-th monster is selected, and the health values of the hero and the i-th monster are x and y before the fight, respectively. After the fight, the health values of the hero and the i-th monster become x−ai and y−A, respectively.
Note that the hero can fight the same monster more than once.

For the safety of the people in the country, please tell them whether the great hero can kill all the monsters (even if the great hero himself is dead after killing the last monster).

Input
Each test contains multiple test cases. The first line contains t (1≤t≤105) — the number of test cases. Description of the test cases follows.

The first line of each test case contains three integers A (1≤A≤106), B (1≤B≤106) and n (1≤n≤105) — the attack power of the great hero, the initial health value of the great hero, and the number of monsters.

The second line of each test case contains n integers a1,a2,…,an (1≤ai≤106), where ai denotes the attack power of the i-th monster.

The third line of each test case contains n integers b1,b2,…,bn (1≤bi≤106), where bi denotes the initial health value of the i-th monster.

It is guaranteed that the sum of n over all test cases does not exceed 105.

Output
For each test case print the answer: “YES” (without quotes) if the great hero can kill all the monsters. Otherwise, print “NO” (without quotes).

Example
input

5
3 17 1
2
16
10 999 3
10 20 30
100 50 30
1000 1000 4
200 300 400 500
1000 1000 1000 1000
999 999 1
1000
1000
999 999 1
1000000
999

output

YES
YES
YES
NO
YES

Note
In the first example: There will be 6 fights between the hero and the only monster. After that, the monster is dead and the health value of the hero becomes 17−6×2=5>0. So the answer is “YES”, and moreover, the hero is still living.

In the second example: After all monsters are dead, the health value of the hero will become 709, regardless of the order of all fights. So the answer is “YES”.

In the third example: A possible order is to fight with the 1-st, 2-nd, 3-rd and 4-th monsters. After all fights, the health value of the hero becomes −400. Unfortunately, the hero is dead, but all monsters are also dead. So the answer is “YES”.

In the fourth example: The hero becomes dead but the monster is still living with health value 1000−999=1. So the answer is “NO”.

题目大意: 第一行给出测试用例的数量t。测试用例的说明如下。
每个测试用例的第一行包含三个整数A(1≤A≤106),B(1≤B≤106)和n(1≤n≤105)——英雄的攻击力,初始生命值和怪物的数量。
每个测试用例的第二行包含n个整数a1,a2,…,an(1≤ai≤106),其中ai表示第i个怪物的攻击力。
每个测试用例的第三行包含n个整数b1,b2,…,bn(1≤bi≤106),其中bi表示第i个怪物的初始生命值。
英雄可以攻击
如果英雄或怪兽的健康值是​​正值(大于或等于1),则认为该英雄或怪兽正在存活;如果其健康值非正值(小于或等于0),则认为他或他已经死亡。
在每次战斗中,英雄都可以选择一个任意的活怪物并与之战斗。假设选择了第i个怪物,并且英雄和第i个怪物的健康值分别是战斗前的x和y。战斗之后,英雄和第i个怪物的健康值分别变为x-ai和y-A。英雄可以同一个怪物战斗不止一次。
请问英雄是否可以杀死所有怪物(即使伟大英雄本人在杀死最后一个怪物之后已经死亡)。
解题思路: 水题,贪心算法,优先解决攻击力低的怪兽。因为英雄和怪兽一次战斗是打出全部伤害的,英雄战斗完为负生命值也可以将怪兽击杀,所以最后一次战斗后英雄负生命值越多越划算。举例:英雄攻击力为3和生命值为4。怪兽生命值和攻击力分别为2和1、3和5、3和2。最佳攻击顺序为2和1、3和2、3和5。此题还须注意计算时可能会超出int范围。
参考代码:

#include <iostream>
#include <stdio.h>
#include <algorithm>

long long int A,B;
int n;
struct monster
{
    long long int a;
    long long int b;
}monsters[100050];

int cmp(struct monster a,struct monster b)
{
    return a.a < b.a;
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int flag = 1;
        scanf("%lld%lld%d",&A,&B,&n);
        for(int i = 0;i < n;i++)
        {
            scanf("%lld",&monsters[i].a);
        }
        for(int i = 0;i < n;i++)
        {
            scanf("%lld",&monsters[i].b);
        }
        std::sort(monsters,monsters + n,cmp);
        for(int i = 0;i < n;i++)
        {
            B -= ((A + monsters[i].b - 1) / A) * monsters[i].a;
            if(B <= -1 * monsters[i].a)
            {
                flag = 0;
                break;
            }
        }
        if(flag)
        {
            printf("YES\n");
        }
        else
        {
            printf("NO\n");
        }
    }
}

Searching Local Minimum

This is an interactive problem.

Homer likes arrays a lot and he wants to play a game with you.

Homer has hidden from you a permutation a1,a2,…,an of integers 1 to n. You are asked to find any index k (1≤k≤n) which is a local minimum.

For an array a1,a2,…,an, an index i (1≤i≤n) is said to be a local minimum if ai<min{ai−1,ai+1}, where a0=an+1=+∞. An array is said to be a permutation of integers 1 to n, if it contains all integers from 1 to n exactly once.

Initially, you are only given the value of n without any other information about this permutation.

At each interactive step, you are allowed to choose any i (1≤i≤n) and make a query with it. As a response, you will be given the value of ai.

You are asked to find any index k which is a local minimum after at most 100 queries.

Interaction
You begin the interaction by reading an integer n (1≤n≤105) on a separate line.

To make a query on index i (1≤i≤n), you should output “? i” in a separate line. Then read the value of ai in a separate line. The number of the “?” queries is limited within 100.

When you find an index k (1≤k≤n) which is a local minimum, output “! k” in a separate line and terminate your program.

In case your query format is invalid, or you have made more than 100 “?” queries, you will receive Wrong Answer verdict.

After printing a query do not forget to output end of line and flush the output. Otherwise, you will get Idleness limit exceeded. To do this, use:

fflush(stdout) or cout.flush() in C++;
System.out.flush() in Java;
flush(output) in Pascal;
stdout.flush() in Python;
see documentation for other languages.
Hack Format

The first line of the hack should contain a single integer n (1≤n≤105).

The second line should contain n distinct integers a1,a2,…,an (1≤ai≤n).

Example
input

5
3
2
1
4
5

output

? 1
? 2
? 3
? 4
? 5
! 3

Note
In the example, the first line contains an integer 5 indicating that the length of the array is n=5.

The example makes five “?” queries, after which we conclude that the array is a=[3,2,1,4,5] and k=3 is local minimum.

题目大意: 这是一道互动题,找出数列的局部最小值(a0和an为+∞)。第一行告知数列长度。发送“?+数字”,查询该位置的数字,查询次数不得大于100,发送“!+数字”发送答案。每次输出后要刷新缓存,不然会报超时错误。
解题思路: 签到题,分治算法。1到n数列的定义为1…n的n个不重复整数,所以数列的局部最小值若唯一的话一定是最小值,且最小值的左边是递减,最小值的右边是递增。因此可以用二分查找,查找最小值的位置。
参考代码:

#include <iostream>
#include <stdio.h>

int num[100050];

void chaxun(int n)
{
    if(num[n] == 0)
    {
        std::cout << "? " << n << std::endl;
        std::cin >> num[n];
    }
}

int main()
{
    int n;
    std::cin >> n;
    num[0] = num[n + 1] = 10000000;
    int l = 1;
    int r = n;
    while(l < r)
    {
        int mid = (l + r) / 2;
        chaxun(mid + 1);
        chaxun(mid);
        if(num[mid + 1] > num[mid])
        {
            r = mid;
        }
        else
        {
            l = mid + 1;
        }
    }
    std::cout << "! " << l << std::endl;
    std::cout.flush();
}

D1. Painting the Array I

The only difference between the two versions is that this version asks the maximal possible answer.

Homer likes arrays a lot. Today he is painting an array a1,a2,…,an with two kinds of colors, white and black. A painting assignment for a1,a2,…,an is described by an array b1,b2,…,bn that bi indicates the color of ai (0 for white and 1 for black).

According to a painting assignment b1,b2,…,bn, the array a is split into two new arrays a(0) and a(1), where a(0) is the sub-sequence of all white elements in a and a(1) is the sub-sequence of all black elements in a. For example, if a=[1,2,3,4,5,6] and b=[0,1,0,1,0,0], then a(0)=[1,3,5,6] and a(1)=[2,4].

The number of segments in an array c1,c2,…,ck, denoted seg©, is the number of elements if we merge all adjacent elements with the same value in c. For example, the number of segments in [1,1,2,2,3,3,3,2] is 4, because the array will become [1,2,3,2] after merging adjacent elements with the same value. Especially, the number of segments in an empty array is 0.

Homer wants to find a painting assignment b, according to which the number of segments in both a(0) and a(1), i.e. seg(a(0))+seg(a(1)), is as large as possible. Find this number.

Input
The first line contains an integer n (1≤n≤105).

The second line contains n integers a1,a2,…,an (1≤ai≤n).

Output
Output a single integer, indicating the maximal possible total number of segments.

Examples
input

7
1 1 2 2 3 3 3

output

6

input

7
1 2 3 4 5 6 7

output

7

Note
In the first example, we can choose a(0)=[1,2,3,3], a(1)=[1,2,3] and seg(a(0))=seg(a(1))=3. So the answer is 3+3=6.

In the second example, we can choose a(0)=[1,2,3,4,5,6,7] and a(1) is empty. We can see that seg(a(0))=7 and seg(a(1))=0. So the answer is 7+0=7.

题目大意: 把一个序列分成两个子序列,求两个子序列总长度最大是多少(重复元素记为一个元素)。
解题思路: 贪心算法。只需要考虑父串当前字符和两个字串最后一个字符的关系。
先求出当前元素距离下一个相同元素的距离。
1、两个子序列末尾元素都相同:接在离下一个相同元素更近的那个。
2、只有一个子序列末尾元素与父序列当前元素相同,那就接在不同的末尾。
3、如果两个子序列末尾元素都与不同,那么就接在离下一个相同元素更近的那个。
参考代码:

#include <iostream>
#include <stdio.h>

int a[100050],next[100050],position[100050];

int main()
{
    int n,t;
    scanf("%d",&n);
    for(int i = 1;i <= n;i++)
    {
        scanf("%d",&a[i]);
    }
    for(int i = n;i >= 0;i--)
    {
        next[i] = position[a[i]] != 0 ? position[a[i]] : n + 1;
        position[a[i]] = i;
    }
    int x = 0,y = 0,answer = 0;
    for(int i = 1;i <= n;i++)
    {
        if(a[x] == a[y])
        {
            answer += a[x] != a[i] ? 1 : 0;
            if(next[x] < next[y])
            {
                x = i;
            }
            else
            {
                y = i;
            }
        }
        else if(a[y] == a[i])
        {
            x = i;
            answer++;
        }
        else if(a[x] == a[i])
        {
            y = i;
            answer++;
        }
        else
        {
            if(next[x] < next[y])
            {
                x = i;
            }
            else
            {
                y = i;
            }
            answer++;
        }
    }
    printf("%d\n",answer);
}

D2. Painting the Array II

The only difference between the two versions is that this version asks the minimal possible answer.

Homer likes arrays a lot. Today he is painting an array a1,a2,…,an with two kinds of colors, white and black. A painting assignment for a1,a2,…,an is described by an array b1,b2,…,bn that bi indicates the color of ai (0 for white and 1 for black).

According to a painting assignment b1,b2,…,bn, the array a is split into two new arrays a(0) and a(1), where a(0) is the sub-sequence of all white elements in a and a(1) is the sub-sequence of all black elements in a. For example, if a=[1,2,3,4,5,6] and b=[0,1,0,1,0,0], then a(0)=[1,3,5,6] and a(1)=[2,4].

The number of segments in an array c1,c2,…,ck, denoted seg©, is the number of elements if we merge all adjacent elements with the same value in c. For example, the number of segments in [1,1,2,2,3,3,3,2] is 4, because the array will become [1,2,3,2] after merging adjacent elements with the same value. Especially, the number of segments in an empty array is 0.

Homer wants to find a painting assignment b, according to which the number of segments in both a(0) and a(1), i.e. seg(a(0))+seg(a(1)), is as small as possible. Find this number.

Input
The first line contains an integer n (1≤n≤105).

The second line contains n integers a1,a2,…,an (1≤ai≤n).

Output
Output a single integer, indicating the minimal possible total number of segments.

Examples
input

6
1 2 3 1 2 2

output

4

input

7
1 2 1 2 1 2 1

output

2

Note
In the first example, we can choose a(0)=[1,1,2,2], a(1)=[2,3] and seg(a(0))=seg(a(1))=2. So the answer is 2+2=4.

In the second example, we can choose a(0)=[1,1,1,1], a(1)=[2,2,2] and seg(a(0))=seg(a(1))=1. So the answer is 1+1=2.

题目大意: 把一个序列分成两个子序列,求两个子序列总长度最小是多少(重复元素记为一个元素)。
解题思路: 贪心算法。只需要考虑父串当前字符和两个字串最后一个字符的关系。
先求出当前元素距离下一个相同元素的距离。
1、两个子序列末尾元素都相同:接在离下一个相同元素更近的那个。
2、只有一个子序列末尾元素与父序列当前元素相同,那就接在不同的末尾。
3、如果两个子序列末尾元素都与不同,那么就接在离下一个相同元素更远的那个。
参考代码:

#include <iostream>
#include <stdio.h>

int a[100050],next[100050],position[100050];

int main()
{
    int n,t;
    scanf("%d",&n);
    for(int i = 1;i <= n;i++)
    {
        scanf("%d",&a[i]);
    }
    for(int i = n;i >= 0;i--)
    {
        next[i] = position[a[i]] != 0 ? position[a[i]] : n + 1;
        position[a[i]] = i;
    }
    int x = 0,y = 0,answer = 0;
    for(int i = 1;i <= n;i++)
    {
        if(a[x] == a[y])
        {
            answer += a[x] != a[i] ? 1 : 0;
            if(next[x] < next[y])
            {
                x = i;
            }
            else
            {
                y = i;
            }
        }
        else if(a[y] == a[i])
        {
            y = i;
        }
        else if(a[x] == a[i])
        {
            x = i;
        }
        else
        {
            if(next[x] > next[y])
            {
                x = i;
            }
            else
            {
                y = i;
            }
            answer++;
        }
    }
    printf("%d\n",answer);
}

E. Continuous City

Some time ago Homer lived in a beautiful city. There were n blocks numbered from 1 to n and m directed roads between them. Each road had a positive length, and each road went from the block with the smaller index to the block with the larger index. For every two (different) blocks, there was at most one road between them.

Homer discovered that for some two numbers L and R the city was (L,R)-continuous.

The city is said to be (L,R)-continuous, if

all paths from block 1 to block n are of length between L and R (inclusive); and
for every L≤d≤R, there is exactly one path from block 1 to block n whose length is d.
A path from block u to block v is a sequence u=x0→x1→x2→⋯→xk=v, where there is a road from block xi−1 to block xi for every 1≤i≤k. The length of a path is the sum of lengths over all roads in the path. Two paths x0→x1→⋯→xk and y0→y1→⋯→yl are different, if k≠l or xi≠yi for some 0≤i≤min{k,l}.

After moving to another city, Homer only remembers the two special numbers L and R but forgets the numbers n and m of blocks and roads, respectively, and how blocks are connected by roads. However, he believes the number of blocks should be no larger than 32 (because the city was small).

As the best friend of Homer, please tell him whether it is possible to find a (L,R)-continuous city or not.

Input
The single line contains two integers L and R (1≤L≤R≤106).

Output
If it is impossible to find a (L,R)-continuous city within 32 blocks, print “NO” in a single line.

Otherwise, print “YES” in the first line followed by a description of a (L,R)-continuous city.

The second line should contain two integers n (2≤n≤32) and m (1≤m≤n(n−1)2), where n denotes the number of blocks and m denotes the number of roads.

Then m lines follow. The i-th of the m lines should contain three integers ai, bi (1≤ai<bi≤n) and ci (1≤ci≤106) indicating that there is a directed road from block ai to block bi of length ci.

It is required that for every two blocks, there should be no more than 1 road connecting them. That is, for every 1≤i<j≤m, either ai≠aj or bi≠bj.

Examples
input

1 1

output

YES
2 1
1 2 1

input

4 6

output

YES
5 6
1 2 3
1 3 4
1 4 5
2 5 1
3 5 1
4 5 1

Note
In the first example there is only one path from block 1 to block n=2, and its length is 1.

In the second example there are three paths from block 1 to block n=5, which are 1→2→5 of length 4, 1→3→5 of length 5 and 1→4→5 of length 6.

题目大意: 给你两个数 L,R(1 <= L <= R <= 106),用至多32个点构造一张DAG,满足从 1 到 n 的所有路径恰有 R − L + 1 条 , 且路径长度值域恰好为 [L,R] 。构造的DAG的点数不超过32,DAG的边只能从小编号连向大编号,并给每条边定一个正边权。
解题思路: 从32个点中取几个从小到大的点构成一个路径集合,路径长度不重复,很容易发现是二进制分解算法。
1.想到二进制分解,且106 << 2 32 ,所以答案一定是“YES”。
2.首先从1点到所有点连出一条线长度为L,则题目转化为求其余点到n点的路径为[1,R - L],这就更明显了,二进制分解R - L。
3.从第i点(i != 1 && i != n)向除n点外比它大的点连一条长度为2^i - 1^ 的线。
4.最后一步就是二进制分解R - L,第i点对应R - L的第i - 1位(因为第1点不参与二进制分解),若R - L的第i - 1位为1,令t = (0xFFFFFFF << (i - 1))) + 1(即将R - L的后i - 1位置零),从第i点连一条长度为t的线到第n点。
5.n = log2(R - L) + 1,所以R = L要单独考虑,即输出

YES
2 1 
1 2 R

参考代码:

#include <iostream>
#include <stdio.h>
#include <math.h>

#define Add(x,y,z) (tot+=sprintf(s+tot,"%d %d %d\n",x,y,z),++cnt)

int cnt,tot;
char s[10000000];

int main(){
    int l,r;
    scanf("%d%d",&l,&r);
    int num = r - l;
    printf("YES\n");
    if(num == 0)
    {
        printf("%d %d\n",2,1);
        printf("%d %d %d\n",1,2,l);
    }
    else
    {
        int n = log2(num) + 1;
        for(int i = 2;i <= n + 2;i++)
        {
            Add(1,i,l);
        }
        for(int i = 2;i < n + 2;i++)
        {
            for(int j = i + 1;j < n + 2;j++)
            {
                Add(i,j,1 << (i - 2));
            }
        }
        for(int i = 2;i < n + 2;i++)
        {
            if((r - l) >> (i - 2) & 1)
            {
                Add(i,n + 2,((r - l) & (0xFFFFFFF << (i - 1))) + 1);
            }
        }
        printf("%d %d\n",n + 2,cnt);
        printf("%s",s);
    }
	return 0;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值