Codeforces Round 944 (Div. 4)解题

A. My First Sorting Problem

题面翻译

t t t 组数据,每组数据给你两个整数 x x x y y y

输出两个整数: x x x y y y 中较小的那个,然后是 x x x y y y 中较大的那个。

题目描述

You are given two integers $ x $ and $ y $ .

Output two integers: the minimum of $ x $ and $ y $ , followed by the maximum of $ x $ and $ y $ .

输入格式

The first line contains a single integer $ t $ ( $ 1 \leq t \leq 100 $ ) — the number of test cases.

The only line of each test case contains two space-separated integers $ x $ and $ y $ ( $ 0 \leq x, y \leq 9 $ ).

输出格式

For each test case, output two integers: the minimum of $ x $ and $ y $ , followed by the maximum of $ x $ and $ y $ .

样例 #1

样例输入 #1

10
1 9
8 4
1 4
3 4
2 0
2 4
6 9
3 3
0 0
9 9

样例输出 #1

1 9
4 8
1 4
3 4
0 2
2 4
6 9
3 3
0 0
9 9

无脑代码

#include<iostream>

using namespace std;

int a,b;
int T;

int main(){
    
    cin>>T;
    
    while(T--){
        cin>>a>>b;
        
        cout<<min(a,b)<<" "<<max(a,b)<<endl;
    }
    
    
    
    return 0;
}

B. Different String

题面翻译

题目描述

给定一个以小写字母构成的字符串 s s s

现在你的任务是,重新排列 s s s 的字符以形成一个不等于 s s s 的新字符串 r r r

输入格式

本题单个测试点内包含多组测试数据。

第一行包含一个整数 t t t 1 ≤ t ≤ 1000 1\leq t\leq 1000 1t1000),表示测试数据组数。

每个测试用例的唯一一行包含一个字符串 s s s,长度最多为 10 10 10,由小写英文字母组成。

输出格式

对于每个测试用例,如果不存在语句中描述的字符串 r r r,则输出NO

否则,输出YES。然后,输出一行一个字符串 r r r,由字符串 s s s 的字母组成。

你可以以任何大小写形式输出YESNO

如果可以有多个答案,则可以输出其中任何一个。

题目描述

You are given a string $ s $ consisting of lowercase English letters.

Rearrange the characters of $ s $ to form a new string $ r $ that is not equal to $ s $ , or report that it’s impossible.

输入格式

The first line contains a single integer $ t $ ( $ 1 \leq t \leq 1000 $ ) — the number of test cases.

The only line of each test case contains a string $ s $ of length at most $ 10 $ consisting of lowercase English letters.

输出格式

For each test case, if no such string $ r $ exists as described in the statement, output “NO” (without quotes).

Otherwise, output “YES” (without quotes). Then, output one line — the string $ r $ , consisting of letters of string $ s $ .

You can output “YES” and “NO” in any case (for example, strings “yEs”, “yes”, and “Yes” will be recognized as a positive response).

If multiple answers are possible, you can output any of them.

样例 #1

样例输入 #1

8
codeforces
aaaaa
xxxxy
co
d
nutdealer
mwistht
hhhhhhhhhh

样例输出 #1

YES
forcodesec
NO
YES
xxyxx
YES
oc
NO
YES
undertale
YES
thtsiwm
NO

提示

In the first test case, another possible answer is $ \texttt{forcescode} $ .

In the second test case, all rearrangements of $ \texttt{aaaaa} $ are equal to $ \texttt{aaaaa} $ .

思路

就判断位数是不是为一和是不是全部相同,此时如果成立就输出 NO

#include<iostream>
#include<map>

using namespace std;

string s;
int T;

int main(){
    cin>>T;
    
    while(T--){
        cin>>s;
        map<char,int>S;
        
        for(char x:s){
            S[x]++;
        }
        int n=s.size();
        if(n==1||S[s[0]]==n){
            puts("NO");
        }else{
            puts("YES");
            cout<<s[n-1]<<s.substr(0,n-1)<<endl;
        }
    }
    return 0;
    
}

C. Clock and Strings

题面翻译

输入 t ( 1 ≤ t ≤ 5940 ) t(1\le t\le 5940) t(1t5940) 行,每行 4 4 4 个整数 a , b , c , d ( 1 ≤ a , b , c , d ≤ 12 ) a,b,c,d(1\le a,b,c,d\le 12) a,b,c,d(1a,b,c,d12),表示钟面上 a , b a, b a,b c , d c, d c,d 两条线段的四个端点所对应的刻度,问这两条线段会不会在钟面上相交。如果会,则输出 YES,不会则输出 NO

题目描述

There is a clock labeled with the numbers $ 1 $ through $ 12 $ in clockwise order, as shown below.

In this example, $ (a,b,c,d)=(2,9,10,6) $ , and the strings intersect.

Alice and Bob have four distinct integers $ a $ , $ b $ , $ c $ , $ d $ not more than $ 12 $ . Alice ties a red string connecting $ a $ and $ b $ , and Bob ties a blue string connecting $ c $ and $ d $ . Do the strings intersect? (The strings are straight line segments.)

输入格式

The first line contains a single integer $ t $ ( $ 1 \leq t \leq 5940 $ ) — the number of test cases.

The only line of each test case contains four distinct integers $ a $ , $ b $ , $ c $ , $ d $ ( $ 1 \leq a, b, c, d \leq 12 $ ).

输出格式

For each test case, output “YES” (without quotes) if the strings intersect, and “NO” (without quotes) otherwise.

You can output “YES” and “NO” in any case (for example, strings “yEs”, “yes”, and “Yes” will be recognized as a positive response).

样例 #1

样例输入 #1

15
2 9 10 6
3 8 9 1
1 2 3 4
5 3 4 12
1 8 2 10
3 12 11 8
9 10 12 1
12 1 10 2
3 12 6 9
1 9 8 4
6 7 9 12
7 12 9 6
10 12 11 1
3 9 6 12
1 4 3 5

样例输出 #1

YES
NO
NO
YES
YES
NO
NO
NO
NO
NO
NO
YES
YES
YES
YES

提示

The first test case is pictured in the statement.

In the second test case, the strings do not intersect, as shown below.

思路

我们为了研究方便就把 a , c a,c a,c 看成比较大的数,我们可以固定红色的线,去看蓝色的线怎么样才能没交点,那么剩下的都是有交点的。

#include<iostream>

using namespace std;

int T;
int a,b,c,d;

int main(){
    cin>>T;
    
    while(T--){
        cin>>a>>b>>c>>d;
        
        if(a>b)swap(a,b);
        
        if(c>d)swap(c,d);
        
        if(b>=d&&c<=a&&d>=a||a<=c&&b>=c&&b<=d){
            puts("YES");
        }else{
            puts("NO");
        }
        
        
    }
    
    return 0;
}

D. Binary Cut

题面翻译

题目描述

给定一个二进制字符串 $ ^{\dagger} $ 。请找到您需要将其切割成的最小片段数,将生成的片段重新排列成有序的二进制字符串。

请注意:

  • 每个字符必须恰好位于其中一个片段中;
  • 这些片段必须是原始字符串的连续子字符串;
  • 你必须在重排中使用所有的片段。

† ^{\dagger} 二进制字符串是由字符 $ \texttt{0}$ 和 1 \texttt{1} 1 组成的字符串。排序后的二进制字符串是一个二进制字符串,使得所有字符 0 \texttt{0} 0 位于所有字符 1 \texttt{1} 1 之前。

输入格式

第一行包含一个整数 t t t 1 ≤ t ≤ 500 1\leq t\leq 500 1t500)——测试用例的数量。

每个测试用例的唯一一行包含一个由 0 \texttt{0} 0 1 \texttt1 1 组成的字符串 s s s 1 ≤ ∣ s ∣ ≤ 500 1 \leq |s| \leq 500 1s500),其中 ∣ s ∣ |s| s 表示字符串 s s s 的长度。

输出格式

对于每个测试用例,输出将字符串重新排列为有序二进制字符串所需的最小分割数量。

题目描述

You are given a binary string $ ^{\dagger} $ . Please find the minimum number of pieces you need to cut it into, so that the resulting pieces can be rearranged into a sorted binary string.

Note that:

  • each character must lie in exactly one of the pieces;
  • the pieces must be contiguous substrings of the original string;
  • you must use all the pieces in the rearrangement.

$ ^{\dagger} $ A binary string is a string consisting of characters $ \texttt{0} $ and $ \texttt{1} $ . A sorted binary string is a binary string such that all characters $ \texttt{0} $ come before all characters $ \texttt{1} $ .

输入格式

The first line contains a single integer $ t $ ( $ 1 \leq t \leq 500 $ ) — the number of test cases.

The only line of each test case contains a single string $ s $ ( $ 1 \leq |s| \leq 500 $ ) consisting of characters $ \texttt{0} $ and $ \texttt{1} $ , where $ |s| $ denotes the length of the string $ s $ .

输出格式

For each test case, output a single integer — the minimum number of pieces needed to be able to rearrange the string into a sorted binary string.

样例 #1

样例输入 #1

6
11010
00000000
1
10
0001111
0110

样例输出 #1

3
1
1
2
1
2

提示

The first test case is pictured in the statement. It can be proven that you can’t use fewer than $ 3 $ pieces.

In the second and third test cases, the binary string is already sorted, so only $ 1 $ piece is needed.

In the fourth test case, you need to make a single cut between the two characters and rearrange them to make the string $ \texttt{01} $ .

思路

贪心题,我们这边要特别注意下,本道题是问块数,不是问切割数;我们通过多列几个样例可以看出如下性质:

  • 当我们遇到一段全是 0 或全是 1 的字符串,就不需要分开;
  • 当我们遇到 01 这个子串时,我们只能保留一个 01 子串;
  • 当我们遇到 10 就一定得分段。
  • 最后的答案要+1,因为本身就是一段。
#include<iostream>
#include<algorithm>
#include<cstring>

using namespace std;

const int N = 510;

int T;

int main(){
    cin>>T;
    
    while(T--){
        string a,b;
        cin>>a;
        b=a;
        
        sort(b.begin(),b.end());
        
        if(a==b){
            puts("1");
            continue;
        }
        
        int n=b.size();
        
        int res=0,pos=0;
        
        for(int i=1;i<n;i++){
            if(a[i]!=a[i-1])res++;
            if(a[i]=='1'&&a[i-1]=='0')pos=1;
        }
        
        if(pos)res--;
        
        cout<<res+1<<endl;
        
    }
    
    return 0;
}

E. Find the Car

题面翻译

一条笔直的公路上有 k k k 个标志,已知这条公路的长度 n n n,第 i i i 个标志位于 a i a_{i} ai 点,一辆大巴车从 0 0 0 点出发,从一个站点到另一个站点匀速行驶,并在 b i b_{i} bi 分钟经过第 i i i 个标志。现给出 q q q 个询问,求大巴车经过 d d d 点的时间(向下取整)。

输入有 t t t 组,对于每组数据的 q q q 个询问,输出一行,用空格间隔。

对于 100 % 100\% 100% 的数据, 1 ≤ t ≤ 1 0 4 1\le t\le 10^4 1t104 k ≤ n ≤ 1 0 9 k\le n\le 10^9 kn109 1 ≤ k , q ≤ 1 0 5 1\le k,q\le 10^5 1k,q105 1 ≤ a 1 < a 2 < … < a k = n 1\le a_1<a_2<\ldots<a_k=n 1a1<a2<<ak=n 1 ≤ b 1 < b 2 < … < b k ≤ 1 0 9 1\le b_1<b_2<\ldots<b_k\le 10^9 1b1<b2<<bk109

题目描述

Timur is in a car traveling on the number line from point $ 0 $ to point $ n $ . The car starts moving from point $ 0 $ at minute $ 0 $ .

There are $ k+1 $ signs on the line at points $ 0, a_1, a_2, \dots, a_k $ , and Timur knows that the car will arrive there at minutes $ 0, b_1, b_2, \dots, b_k $ , respectively. The sequences $ a $ and $ b $ are strictly increasing with $ a_k = n $ .

Between any two adjacent signs, the car travels with a constant speed. Timur has $ q $ queries: each query will be an integer $ d $ , and Timur wants you to output how many minutes it takes the car to reach point $ d $ , rounded down to the nearest integer.

输入格式

The first line contains a single integer $ t $ ( $ 1 \leq t \leq 10^4 $ ) — the number of test cases.

The first line of each test case contains three integers $ n $ , $ k $ , and $ q $ , ( $ k \leq n \leq 10^9 $ ; $ 1 \leq k, q \leq 10^5 $ ) — the final destination, the number of points Timur knows the time for, and the number of queries respectively.

The second line of each test case contains $ k $ integers $ a_i $ ( $ 1 \leq a_i \leq n $ ; $ a_i < a_{i+1} $ for every $ 1 \leq i \leq k-1 $ ; $ a_k = n $ ).

The third line of each test case contains $ k $ integers $ b_i $ ( $ 1 \leq b_i \leq 10^9 $ ; $ b_i < b_{i+1} $ for every $ 1 \leq i \leq k-1 $ ).

Each of the following $ q $ lines contains a single integer $ d $ ( $ 0 \leq d \leq n $ ) — the distance that Timur asks the minutes passed for.

The sum of $ k $ over all test cases doesn’t exceed $ 10^5 $ , and the sum of $ q $ over all test cases doesn’t exceed $ 10^5 $ .

输出格式

For each query, output a single integer — the number of minutes passed until the car reaches the point $ d $ , rounded down.

样例 #1

样例输入 #1

4
10 1 3
10
10
0
6
7
10 2 4
4 10
4 7
6
4
2
7
1000000000 1 1
1000000000
1000000000
99999999
6 1 3
6
5
2
6
5

样例输出 #1

0 6 7 
5 4 2 5 
99999999 
1 5 4

提示

For the first test case, the car goes from point $ 0 $ to point $ 10 $ in $ 10 $ minutes, so the speed is $ 1 $ unit per minute and:

  • At point $ 0 $ , the time will be $ 0 $ minutes.
  • At point $ 6 $ , the time will be $ 6 $ minutes.
  • At point $ 7 $ , the time will be $ 7 $ minutes.

For the second test case, between points $ 0 $ and $ 4 $ , the car travels at a speed of $ 1 $ unit per minute and between $ 4 $ and $ 10 $ with a speed of $ 2 $ units per minute and:

  • At point $ 6 $ , the time will be $ 5 $ minutes.
  • At point $ 4 $ , the time will be $ 4 $ minutes.
  • At point $ 2 $ , the time will be $ 2 $ minutes.
  • At point $ 7 $ , the time will be $ 5.5 $ minutes, so the answer is $ 5 $ .

For the fourth test case, the car travels with $ 1.2 $ units per minute, so the answers to the queries are:

  • At point $ 2 $ , the time will be $ 1.66\dots $ minutes, so the answer is $ 1 $ .
  • At point $ 6 $ , the time will be $ 5 $ minutes.
  • At point $ 5 $ , the time will be $ 4.16\dots $ minutes, so the answer is $ 4 $ .

思路

通过观察样例我们可以发现,我们可以通过二分找到要查询的位置在哪块牌子和牌子之间,因为是匀速行使,然后我们带入公式可以很容易得到下面的代码:

  • 注意:题目是下取整。
//二分区间,然后里面求平均速度

#include<iostream>
#include<algorithm>

using namespace std;

const int N = 1e5+10;

int a[N],b[N];
int n,k,q;
int T;

int main(){
    cin>>T;
    
    while(T--){
        cin>>n>>k>>q;
        
        for(int i=1;i<=k;i++)cin>>a[i];
        for(int i=1;i<=k;i++)cin>>b[i];
        
        
        while(q--){
            int t;
            cin>>t;
            int p=lower_bound(a+1,a+1+k,t)-a-1;
            int x=p,y=p+1;
            // cout<<x<<' '<<y<<endl;
            double ans=b[x]+(double)(t-a[x])*(b[y]-b[x])/(a[y]-a[x]);
            cout<<(int)ans<<' ';
        }
        puts("");
    }
    
    return 0;
}

F .Circle Perimeter

题面翻译

给定整数 r r r,求出与 ( 0 , 0 ) (0,0) (0,0) 的欧几里得距离大于或等于 r r r 但严格小于 r + 1 r+1 r+1 的格点的数量。
格点是具有整数坐标的点。从 ( 0 , 0 ) (0,0) (0,0) 到点 ( x , y ) (x,y) (x,y) 的欧几里得距离是 x 2 + y 2 \sqrt{x^2+y^2} x2+y2

题目描述

Given an integer $ r $ , find the number of lattice points that have a Euclidean distance from $ (0, 0) $ greater than or equal to $ r $ but strictly less than $ r+1 $ .

A lattice point is a point with integer coordinates. The Euclidean distance from $ (0, 0) $ to the point $ (x,y) $ is $ \sqrt{x^2 + y^2} $ .

输入格式

The first line contains a single integer $ t $ ( $ 1 \leq t \leq 1000 $ ) — the number of test cases.

The only line of each test case contains a single integer $ r $ ( $ 1 \leq r \leq 10^5 $ ).

The sum of $ r $ over all test cases does not exceed $ 10^5 $ .

输出格式

For each test case, output a single integer — the number of lattice points that have an Euclidean distance $ d $ from $ (0, 0) $ such that $ r \leq d < r+1 $ .

样例 #1

样例输入 #1

6
1
2
3
4
5
1984

样例输出 #1

8
16
20
24
40
12504

提示

The points for the first three test cases are shown below.

思路

这道题我们肯定不能直接枚举 x , y x,y x,y,但我们可以取巧,先枚举 x x x,然后缩小枚举 y y y 的范围。怎么简化呢?我们可以对公式下手:

x 2 + y 2 \sqrt{x^2+y^2} x2+y2
再结合题目的范围得出:
r 2 − x 2 ≤ y ≤ ( r + 1 ) 2 − x 2 \sqrt{r^2-x^2}\le y\le \sqrt{(r+1)^2-x^2} r2x2 y(r+1)2x2 ,那么这样就很好写代码了。

#include<iostream>
#include<cmath>

using namespace std;

#define int long long

int T;
int n;

signed main(){
    cin>>T;
    
    while(T--){
        cin>>n;
        int res=0;
        
        int r1=n*n,r2=(n+1)*(n+1);
        
        for(int i=0;i<=n+1;i++){
            int x=i*i;
            int m1=(int)ceil(sqrt((double)max(0ll,r1-x)));
            int m2=(int)floor(sqrt((double)(r2-1-x)));
            for(int y=m1;y<=m2;y++){
                if(x==0||y==0)res+=2;
                else res+=4;
            }
        }
        
        cout<<res<<endl;
    }
    
    return 0;
}

G. XOUR

题面翻译

给你一个由 n n n 个非负整数组成的数组 a a a

如果 $ a_i\mathsf{XOR}a_j < 4 $,你可以交换位置 i i i j j j 的元素,其中 X O R \mathsf{XOR} XORbitwise XOR operation

求进行不限次操作后字典序最小的序列。

题目描述

You are given an array $ a $ consisting of $ n $ nonnegative integers.

You can swap the elements at positions $ i $ and $ j $ if $ a_i\mathsf{XOR}a_j < 4 $ , where $ \mathsf{XOR} $ is the bitwise XOR operation.

Find the lexicographically smallest array that can be made with any number of swaps.

An array $ x $ is lexicographically smaller than an array $ y $ if in the first position where $ x $ and $ y $ differ, $ x_i < y_i $ .

输入格式

The first line contains a single integer $ t $ ( $ 1 \leq t \leq 10^4 $ ) — the number of test cases.

The first line of each test case contains a single integer $ n $ ( $ 1 \leq n \leq 2\cdot10^5 $ ) — the length of the array.

The second line of each test case contains $ n $ integers $ a_i $ ( $ 0 \leq a_i \leq 10^9 $ ) — the elements of the array.

It is guaranteed that the sum of $ n $ over all test cases does not exceed $ 2 \cdot 10^5 $ .

输出格式

For each test case, output $ n $ integers — the lexicographically smallest array that can be made with any number of swaps.

样例 #1

样例输入 #1

4
4
1 0 3 2
5
2 7 1 5 6
8
1 2 1 2 1 2 1 2
4
16 4 1 64

样例输出 #1

0 1 2 3 
1 5 2 6 7 
1 1 1 1 2 2 2 2 
16 4 1 64

提示

For the first test case, you can swap any two elements, so we can produce the sorted array.

For the second test case, you can swap $ 2 $ and $ 1 $ (their $ \mathsf{XOR} $ is $ 3 $ ), $ 7 $ and $ 5 $ (their $ \mathsf{XOR} $ is $ 2 $ ), and $ 7 $ and $ 6 $ (their $ \mathsf{XOR} $ is $ 1 $ ) to get the lexicographically smallest array.

思路

a i ⊕ a j < 4 a_i \oplus a_j <4 aiaj<4 入手。

这边有个性质就是:若 a i ⊕ a j < 4 a_i \oplus a_j <4 aiaj<4,当且仅当 ⌊ a i 4 ⌋ = ⌊ a j 4 ⌋ \lfloor \frac{a_i}{4}\rfloor = \lfloor \frac{a_j}{4} \rfloor 4ai=4aj

  • 这里我们想到用 map 容器。把里面的值从小到大排序,在一个个填充到答案数组中。
#include<iostream>
#include<queue>
#include<algorithm>
#include<map>

using namespace std;

const int N = 2e5+10;

int w[N];
int n;
int T;

int main(){
    cin>>T;
    
    while(T--){
        cin>>n;
        map<int,priority_queue<int,vector<int>,greater<int>>> mp;
        for(int i=1;i<=n;i++){
            cin>>w[i];
            mp[w[i]>>2].push(w[i]);
        }
        
        for(int i=1;i<=n;i++){
            cout<<mp[w[i]>>2].top()<<' ';
            mp[w[i]>>2].pop();
        }
        puts("");
    }
    
    return 0;
}

H. ±1

题面翻译

Bob 有一个 3 × n 3 \times n 3×n 的网格,其中每个单元格包含 a i a_i ai − a i -a_i ai,其中 1 ≤ i ≤ n 1 \leq i \leq n 1in。例如,对于 n = 4 n=4 n=4 的网格可能是:

[ a 1 − a 2 − a 3 − a 2 − a 4 a 4 − a 1 − a 3 a 1 a 2 − a 2 a 4 ] \begin{bmatrix} a_1 & -a_2 & -a_3 & -a_2 \\ -a_4 & a_4 & -a_1 & -a_3 \\ a_1 & a_2 & -a_2 & a_4 \end{bmatrix} a1a4a1a2a4a2a3a1a2a2a3a4

Alice 和 Bob 玩一个游戏,规则如下:

  • Bob 显示网格给 Alice。
  • Alice 选择一个包含 1 1 1 − 1 -1 1 的数组 [ a 1 , a 2 , ⋯   , a n ] [a_1, a_2, \cdots, a_n] [a1,a2,,an]
  • Bob 用这些值替换网格中的 a i a_i ai,生成一个只包含 1 1 1 − 1 -1 1 的网格。
  • Bob 对每列的元素进行非降序排序。
  • 如果中间一行全是 1 1 1,则 Alice 获胜;否则 Bob 获胜。

例如,Alice 选择 [ 1 , − 1 , − 1 , 1 ] [1, -1, -1, 1] [1,1,1,1],则结果如下:

[ 1 1 1 1 − 1 1 − 1 1 1 − 1 1 1 ] → 排序 [ − 1 − 1 − 1 1 1 1 1 1 1 1 1 1 ] \begin{bmatrix} 1 & 1 & 1 & 1 \\ -1 & 1 & -1 & 1 \\ 1 & -1 & 1 & 1 \end{bmatrix} \xrightarrow{\text{排序}} \begin{bmatrix} -1 & -1 & -1 & 1 \\ 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 \end{bmatrix} 111111111111 排序 111111111111

由于中间一行全是 1 1 1,Alice 获胜。

现在给定 Bob 的网格,确定 Alice 是否可以选择数组 a a a 来赢得游戏。

Translate by JacoAquamarine

题目描述

Bob has a grid with $ 3 $ rows and $ n $ columns, each of which contains either $ a_i $ or $ -a_i $ for some integer $ 1 \leq i \leq n $ . For example, one possible grid for $ n=4 $ is shown below:

[ a 1 − a 2 − a 3 − a 2 − a 4 a 4 − a 1 − a 3 a 1 a 2 − a 2 a 4 ] \begin{bmatrix} a_1 & -a_2 & -a_3 & -a_2 \\ -a_4 & a_4 & -a_1 & -a_3 \\ a_1 & a_2 & -a_2 & a_4 \end{bmatrix} a1a4a1a2a4a2a3a1a2a2a3a4

Alice and Bob play a game as follows:

  • Bob shows Alice his grid.
  • Alice gives Bob an array a 1 , a 2 , ⋯   , a n a_1, a_2, \cdots, a_n a1,a2,,an of her choosing, whose elements are all − 1 -1 1 or 1 1 1.
  • Bob substitutes these values into his grid to make a grid of $ -1 $ s and $ 1 $ s.
  • Bob sorts the elements of each column in non-decreasing order.
  • Alice wins if all the elements in the middle row are $ 1 $ ; otherwise, Bob wins.

For example, suppose Alice gives Bob the array [ 1 , − 1 , − 1 , 1 ] [1, -1, -1, 1] [1,1,1,1] for the grid above. Then the following will happen (colors are added for clarity):

[ a 1 − a 2 − a 3 − a 2 − a 4 a 4 − a 1 − a 3 a 1 a 2 − a 2 a 4 ] → [ 1 , − 1 , − 1 , 1 ] [ 1 1 1 1 − 1 1 − 1 1 1 − 1 1 1 ] → sort each column [ − 1 − 1 − 1 1 1 1 1 1 1 1 1 1 ] \begin{bmatrix} \color{red}{a_1} & \color{green}{-a_2} & \color{blue}{-a_3} & \color{green}{-a_2} \\ -a_4 & a_4 & \color{red}{-a_1} & \color{blue}{-a_3} \\ \color{red}{a_1} & \color{green}{a_2} & \color{green}{-a_2} & a_4 \end{bmatrix} \xrightarrow{[\color{red}{1},\color{green}{-1},\color{blue}{-1},1]} \begin{bmatrix} \color{red}{1} & \color{green}{1} & \color{blue}{1} & \color{green}{1} \\ -1 & 1 & \color{red}{-1} & \color{blue}{1} \\ \color{red}{1} & \color{green}{-1} & \color{green}{1} & 1 \end{bmatrix} \xrightarrow{\text{sort each column}} \begin{bmatrix} -1 & -1 & -1 & 1 \\ \mathbf{1} & \mathbf{1} & \mathbf{1} & \mathbf{1} \\ 1 & 1 & 1 & 1 \\ \end{bmatrix} a1a4a1a2a4a2a3a1a2a2a3a4 [1,1,1,1] 111111111111 sort each column 111111111111

Since the middle row is all $ 1 $ , Alice wins. Given Bob’s grid, determine whether or not Alice can choose the array a a a to win the game.

输入格式

The first line contains a single integer $ t $ ( $ 1 \leq t \leq 1000 $ ) — the number of test cases.

The first line of each test case contains a single integer $ n $ ( $ 2 \leq n \leq 500 $ ) — the number of columns of Bob’s grid.

The next three lines each contain $ n $ integers, the $ i $ -th of which contains $ g_{i,1}, g_{i,2}, \dots, g_{i,n} $ ( $ -n \leq g_{i,j} \leq n $ , $ g_{i,j} \neq 0 $ ), representing Bob’s grid.

If cell $ x > 0 $ is in the input, that cell in Bob’s grid should contain $ a_x $ ; if $ x < 0 $ is in the input, that cell in Bob’s grid should contain $ -a_{-x} $ . See the sample input and notes for a better understanding.

输出格式

For each test case, output YES (without quotes) if Alice can win, and NO (without quotes) otherwise.

You can output YES and NO in any case (for example, strings yEs, yes, and Yes will be recognized as a positive response).

样例 #1

样例输入 #1

4
4
1 -2 -3 -2
-4 4 -1 -3
1 2 -2 4
2
1 2
-1 -2
2 -2
5
1 2 3 4 5
-2 3 -4 -5 -1
3 -5 1 2 2
6
1 3 -6 2 5 2
1 3 -2 -3 -6 -5
-2 -1 -3 2 3 1

样例输出 #1

YES
NO
YES
NO

提示

The first test case is described in the statement.

In the second test case, Bob’s grid is as follows:

[ a 1 a 2 − a 1 − a 2 a 2 − a 2 ] \begin{bmatrix} a_1 & a_2 \\ -a_1 & -a_2 \\ a_2 & -a_2 \end{bmatrix} a1a1a2a2a2a2

For the last column to have $ 1 $ in the middle row when sorted, Alice must pick $ a_2 = -1 $ . However, it is then impossible to choose $ a_1 $ such that the first column has $ 1 $ in the middle when sorted. Thus, Alice cannot win.

In the third test case, Alice can pick $ a = [1,1,1,1,1]$.

思路

本道题因为每个数要么取 1 1 1,要么取 − 1 -1 1,然后还有一些限制,就是每列要排序,然后使得中间的数字均相同则输出 YES,反之为 NO,那么这就很像是 2-SAT 的题了,但是本题的要求是基于三元组的,该如何构造二元关系使其满足条件?

转换一下条件可得三数中至多有一个 − 1 -1 1(只有这样才能满足排序后中间全是 1 1 1)。我们发现若任取两数必有至少一个数为 1 1 1,那么就至多只有一个数为 − 1 -1 1,因为不可能同时取到两个 − 1 -1 1。因此我们就找到了构造方式:三个数之间两两连「 a i a_i ai 1 1 1 a j a_j aj 1 1 1」的边,将负号看成取反,剩下的只需要用一下我们的模板即可。


总的思路参考:
在这里插入图片描述
来源


#include<iostream>
#include<algorithm>
#include<cstring>

using namespace std;

const int N = 2e6+10,M = (N)*2+10;

int e[M],w[M],h[N],ne[M],idx;
bool ins[N];
int id[N],ts,cnt;
int low[N],dfn[N];
int stk[N],top;
int n,m;
int a[4][N];
int T;

void add(int a,int b){
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}

void targin(int u){
    low[u]=dfn[u]=++ts;
    stk[++top]=u,ins[u]=true;
    
    for(int i=h[u];~i;i=ne[i]){
        int ver=e[i];
        
        if(!dfn[ver]){
            targin(ver);
            low[u]=min(low[u],low[ver]);
        }else if(ins[ver]){
            low[u]=min(low[u],dfn[ver]);
        }
    }
    
    if(low[u]==dfn[u]){
        int y;
        cnt++;
        do{
            y=stk[top--];
            ins[y]=false;
            id[y]=cnt;
        }while(y!=u);
    }
    
}

int main(){
    
    cin>>T;
    
    while(T--){
        
        idx=0;
        memset(h,-1,sizeof h);
        
        cin>>n;
        
        for(int i=1;i<=3;i++){
            for(int j=1;j<=n;j++){
                cin>>a[i][j];
            }
        }
        
        for(int i=1;i<=n;i++){//每列
            for(int j=1;j<=3;j++){
                for(int k=1;k<=3;k++){
                    if(j==k)continue;
                    if(a[j][i]<0&&a[k][i]<0)add(-a[j][i]+n,-a[k][i]);
                    if(a[j][i]<0&&a[k][i]>0)add(-a[j][i]+n,a[k][i]+n);
                    if(a[j][i]>0&&a[k][i]<0)add(a[j][i],-a[k][i]);
                    if(a[j][i]>0&&a[k][i]>0)add(a[j][i],a[k][i]+n);
                }
            }
        }
        
        top=cnt=ts=0;
        
        for(int i=1;i<=2*n;i++){
            if(!dfn[i]){
                targin(i);
            }
        }
        
        bool f=false;
        
        for(int i=1;i<=n;i++){
            if(id[i]==id[i+n]){
                f=true;
                break;
            }
        }
        
        if(f)puts("NO");
        else puts("YES");
        
        
        for(int i=1;i<=n*2;i++)dfn[i]=low[i]=id[i]=stk[i]=ins[i]=0;
        
    }
    
    
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

green qwq

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值