BestCoder Round #27
Jump and Jump...
Time Limit: 2000/1000 MS
(Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 0 Accepted Submission(s): 0
Problem Description
There are n kids and they want to know who can jump
the farthest. For each kid, he can jump three times and the distance he jumps
is maximum distance amount all the three jump. For example, if the distance of
each jump is (10, 30, 20), then the farthest distance he can jump is 30. Given
the distance for each jump of the kids, you should find the rank of each kid.
Input
There are multiple test cases. The first
line of input contains an integer T (1≤T≤100), indicating the number of test cases.
For each test case: The first line contains an integer n (2≤n≤3), indicating the number of kids. For the
next n lines, each line contains three integers ai,bi and ci (1≤ai,bi,ci,≤300), indicating the distance for each jump
of the i-th kid. It's guaranteed that the final rank of each kid
won't be the same (ie. the farthest distance each kid can jump won't be the
same).
Output
For each test case, you should output a
single line contain n integers, separated by one space. The i-th integer indicating the rank of i-th kid.
Sample Input
2
3
10 10 10
10 20 30
10 10 20
2
3 4 1
1 2 1
Sample Output
3 1 2
1 2
Hint
For the first case, the farthest
distance each kid can jump is 10, 30 and 20. So the rank is 3, 1, 2.
Jump and Jump...
Time Limit: 2000/1000 MS
(Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 714 Accepted Submission(s): 422
问题描述
有n小孩在比赛跳远,看谁跳的最远。每个小孩可以跳3次,这个小孩的成绩就是三次距离里面的最大值。例如,一个小孩跳3次的距离分别时10, 30和20,那么这个小孩的成绩就是30。给出每个孩子三次跳的距离,问最终每个孩子的排名是多少。
输入描述
输入文件的第一行有一个整数T (1≤T≤100),表示测试数据的组数。对于每组测试数据:第一行包括一个整数n (2≤n≤3), 表示孩子的数目. 接下来n行, 每行包含三个整数ai,bi 和 ci (1≤ai,bi,ci,≤300), 表示第i个小孩每次的跳的距离。输入数据保证每个孩子的成绩互不相同。
输出描述
对于每组数据,输出一行包含n个整数,用一个空格隔开。第i个数表示第i个小孩的最终名次。
输入样例
2
3
10 10 10
10 20 30
10 10 20
2
3 4 1
1 2 1
输出样例
3 1 2
1 2
提示:
对于第一组数据,3个孩子的成绩分别时10, 20和30。因此他们最终排名依次是3, 1和2.
想复杂了,第一次做这种比赛;其实就是把最好的成绩排个顺序,就可以了!
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std; struct node
{
int id;
int mlen;
}a[];
int cmp(node x,node y)
{
return x.mlen>y.mlen;
}
int ss[];
int main()
{
int T;
int ans,i,j,n;
int x,y,z;
scanf("%d",&T);
while(T--)
{
memset(a,,sizeof(a));
scanf("%d",&n);
for(i=;i<=n;i++)
{
scanf("%d%d%d",&x,&y,&z);
int tmp=max(x,y);
tmp=max(tmp,z);
a[i].id=i;
a[i].mlen=tmp;
}
sort(a+,a+n+,cmp);
for(i=;i<=n;i++)
ss[a[i].id]=i;
printf("%d",ss[]);
for(j=;j<=n;j++)
printf(" %d",ss[j]);
printf("\n"); }
return ;
}
Taking Bus
Time Limit: 10000/5000 MS
(Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 0 Accepted Submission(s): 0
Problem Description
Bestland has a very long road and there
are n bus station along the road, which are numbered 1 to n from left to right. There are m persons wanting to take the bus to some
other station. You task is to find the time needed for each person. Note: All
the other information you need is below. Please read the statment carefully.
Input
There are multiple test cases. The first
line of input contains an integer T (1≤T≤60), indicating the number of test cases.
For each test case: The first line contains two integers n and m (2≤n,m≤105), indicating the number of bus stations
and number of people. In the next line, there are n−1 integers, d1,d2,…,dn−1 (1≤di≤109). The i-th integer means the distance between
bus station i and i+1 is di (1≤i<n). In the next m lines, each contains two integers xi and yi (1≤xi,yi≤n,xi≠yi), which means i-th person is in bus station xi and wants goto bus station yi. (1≤i≤m)
What else you should know is that for the i-th person, the bus starts at bus
station ((i−1) mod n)+1 and drives to right. When the bus
arrives at station n, it will turn around and drive from
right to left. Similarly, When the bus arrives at station 1, it will turn around and drive from
left to right. You can assume that the bus drives one meter per second. And you
should only consider the time that the bus drives and ignore the others.
Output
For each person, you should output one
integer which is the minimum time needed before arriving bus station yi.
Sample Input
1
7 3
2 3 4 3 4 5
1 7
4 5
5 4
Sample Output
21
10
28
Hint
For the first person, the bus starts at
bus station 1, and the person takes in bus at time 0. After 21 seconds, the bus
arrives at bus station 7. So the time needed is 21 seconds. For the second
person, the bus starts at bus station 2. After 7 seconds, the bus arrives at
bus station 4 and the person takes in the bus. After 3 seconds, the bus arrives
at bus station 5. So the time needed is 10 seconds. For the third person, the
bus starts at bus station 3. After 7 seconds, the bus arrives at bus station 5
and the person takes in the bus. After 9 seconds, the bus arrives at bus
station 7 and the bus turns around. After 12 seconds, the bus arrives at bus
station 4. So the time needed is 28 seconds.
Taking Bus
Time Limit: 10000/5000 MS
(Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 954 Accepted Submission(s): 255
问题描述
Bestland有一条非常长的马路,马路上设有n个公交汽车站。公交汽车站从左到右标号为1到n。有m个人想要乘公交。你的任务是找出每个人到终点为止所需要的时间。注意:你需要用来解决这道题目的信息在Input里面,请仔细阅读。
输入描述
输入的第一行包含一个整数T (1≤T≤60),表示测试数据的组数。对于每组测试数据:第一行包含两个整数n和m (2≤n,m≤105),表示公交车站的数目和乘客的数目。 接下来一行包含n−1个整数, d1,d2,…,dn−1 (1≤di≤109).
di表示第i个公交站和第i+1个公交站之间的距离。在接下来的m行, 每行包含两个整数xi和yi (1≤xi,yi≤n,xi≠yi), 表示第i个人时刻0的时候在第xi个公交站并且想要到第yi个公交站去。(1≤i≤m)
对于第i个人, 公交车在第((i−1) mod n)+1个公交站点在时刻0的时候,并且公交一开始往右开。公交到达站点n的时候会立刻转向往左开,同样当公交到达站点1的时候也会立刻转向往右开。你可以认为公交每秒只开一个单位距离,你只需要考虑公交开的时间。
输出描述
对于每个人,输出到达yi个公交站点需要的最少时间。
输入样例
1
7 3
2 3 4 3 4 5
1 7
4 5
5 4
输出样例
21
10
28
提示:
对于第一个人, 公交在站点1出发, 然后这个人在时刻0上车。21秒之后,公交到达站点7。
对于第二个人,公交在站点2出发。7秒之后,公交到达站点4,这个人上车。之后又过了3秒,公交到达站点5.总共用了10秒。
对于第三个人,公交在站点3出发。7秒之后,公交到达站点5,这个人上车。之后过了9秒,公交达到站点7,然后转向开往站点0。之后经过12秒,公交达到站点4。因此总共需要28秒时间。
出这题的时间也不够快,其实就是个模拟搭公车,自己动手试试就知道了!
分情况讨论就这么简单。。。我也是醉了。
#include<cstdio>
#include<iostream>
using namespace std; __int64 lenz[],lenf[],len;//被I64害了!
int main()
{
int T,n,m;
int i,j,k;
int st,et;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
lenz[]=;
lenf[n]=;
for(i=;i<=n;i++)
{
scanf("%I64d",&len);
lenz[i]=lenz[i-]+len;
}
for(i=n-;i>;i--)
{
lenf[i]=lenz[n]-lenz[i];
}
int ss;
len=;
for(i=;i<=m;i++)
{
scanf("%d%d",&st,&et);
ss=(i-)%n+;
if(st==et) len=;
else if(st>et)
{
// if(ss>st)
len=lenz[n]-lenz[ss]+lenf[et];
// else
// len=lenz[n]-lenz[ss]+lenf[et];
}
else
{
if(ss==st)
len=lenz[et];
if(ss>st)
len=lenf[]+lenz[n]-lenz[ss]+lenz[et];
else
len=lenz[et]-lenz[ss];
}
printf("%I64d\n",len);
}
}
return ;
}
Matching on Array
Time Limit: 4000/2000 MS
(Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 0 Accepted Submission(s): 0
Problem Description
Alice has a sequence {a1,a2,…,an} with n positive integers. Bob has some
positive integer sequences with different size. Alice wants to know the total
occurrences of every sequence Bob has in Alice's sequence (the occurrences are
allowed to overlap).
We say one sequence B occurs in another sequence A if there is a contiguous subsequence of
A that is the same as B after scaled by a positive real factor.
For example A={2,4,8,16},B={1,2} then B occurs three times in A. The occurrences are {2,4}, {4,8} and {8,16}. And the factor is 0.5, 0.25 and 0.125.
Input
There are multiple test cases. The first
line of input contains an integer T (1≤T≤30), indicating the number of test cases.
For each test case:
The first line contains two integer n and m (1≤n,m≤100000), indicating the size of Alice's
sequence and the number of sequences Bob has. In the next line, there are n integers, a1,a2,…,an, indicating Alice's sequence. In the
following m lines, each starts with an integer ki(1≤ki≤300000) - the size of the sequence. Then ki space separated positive integers
follow, indicating the sequence.
The total sum of ki is less than or equal to 1000000. Other
integers are between 1 and 10000, inclusive.
Output
For each test case, output a single line
with a single integer, indicating the total number of occurrences.
Sample Input
2
4 1
2 4 8 16
2 1 2
5 3
2 4 2 4 6
3 1 2 1
1 5
2 16 8
Sample Output
3
7
Hint
For sample 1, please refer to the
problem description. For sample 2, {1, 2, 1} occurs only once, {5} occurs five
times and {16, 8} occurs only once.
Matching on Array
Time Limit: 4000/2000 MS
(Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 142 Accepted Submission(s): 28
问题描述
Alice有一个大小为n的正整数序列{a1,a2,…,an}。Bob也有一些正整数序列。Alice想要知道对于Bob的每个序列,他们在Alice的序列中出现的总次数是多少。
对于两个序列A和B,如果A中有一个连续子序列在乘以某个缩放系数之后和B一样的话,那么B在A中出现。
例如,A={2,4,8,16},B={1,2}, 那么B在A中出现了3次。对应A中的子序列为{2,4}, {4,8}和{8,16},缩放系数分别是 0.5, 0.25和0.125。
输入描述
输入第一行包含一个整数T (1≤T≤30)表示测试数据组数。对于每组数据:
第一行包含两个整数n和m (1≤n,m≤100000),分别表示Alice的序列大小和Bob拥有的序列的个数。接下来一行包含n个整数,a1,a2,…,an,表示Alice的序列。接下来m行,每行的第一个数是ki(1≤ki≤300000)表示这个序列的大小。接下来ki个用空格分开的正整数,表示这个序列。
保证所有ki的和小于等于1000000。其他整数范围介于1和10000之间(包括1和10000)。
输出描述
对于每组数据,输出一个整数表示出现的总次数。
输入样例
2
4 1
2 4 8 16
2 1 2
5 3
2 4 2 4 6
3 1 2 1
1 5
2 16 8
输出样例
3
7
还没想到很好的办法,题目意思就是匹配数组!问B数组的子数组在A的子数组中出现的次数(倍数关系)有好方法的可以和我讨论哦。
#include <iostream>
#include <fstream>
#include <algorithm>
using namespace std; const int maxn = + ; struct Tnode {
int a, b;
Tnode (int c = , int d = ) : a(c), b(d) {
}
} d[maxn]; bool operator < (Tnode &a, Tnode &b) {
if (a.a == b.a) return a.b < b.b;
return a.a < b.a;
} bool operator > (Tnode &a, Tnode &b) {
if (a.a == b.a) return a.b > b.b;
return a.a > b.a;
} bool operator == (Tnode &a, Tnode &b) {
return a.a == b.a && a.b == b.b;
} int gcd(int a, int b) {
if (b == ) return a;
return gcd(b, a % b);
} bool cmp(int a, int b) {
return d[a] < d[b];
} int n, m;
int ra[maxn], rb[maxn], sum[maxn], rank[maxn], sa[maxn], inx[maxn]; bool equal(int *r, int a, int b, int j) {
return r[a] == r[b] && r[a + j] == r[b + j];
} void Sa() {
int i, j, p, *x = ra, *y = rb, *t, m = n;
for (i = ; i < m; i++) sum[i] = ;
for (i = ; i < n; i++) sum[ x[i] = rank[i] ]++;
for (i = ; i < m; i++) sum[i] += sum[i - ];
for (i = n - ; i > -; i--) sa[ --sum[ x[i] ] ] = i; for (j = , p = ; p < n; j <<= ) {
for (i = n - j, p = ; i < n; i++) y[p++] = i;
for (i = ; i < n; i++)
if (sa[i] >= j) y[p++] = sa[i] - j; for (i = ; i < m; i++) sum[i] = ;
for (i = ; i < n; i++) sum[ x[i] ]++;
for (i = ; i < m; i++) sum[i] += sum[i - ];
for (i = n - ; i > -; i--) sa[ --sum[ x[ y[i] ] ] ] = y[i]; t = x; x = y; y = t;
p = ;
x[ sa[] ] = ;
for (i = ; i < n; i++)
if (equal(y, sa[i], sa[i - ], j)) x[ sa[i] ] = p - ;
else x[ sa[i] ] = p++;
}
n--;
for (i = ; i < n; i++) sa[i] = sa[i + ];
} void Init() {
scanf("%d%d", &n, &m);
int pre = , c;
scanf("%d", &pre);
for (int i = ; i < n - ; i++) {
scanf("%d", &c);
d[i] = Tnode(c / gcd(pre, c), pre / gcd(pre, c));
inx[i] = i;
pre = c;
}
d[n - ] = Tnode(, );
inx[n - ] = n - ; sort(inx, inx + n, cmp); int p = ;
rank[ inx[] ] = p;
for (int i = ; i < n; i++)
if (d[ inx[i] ] == d[ inx[i - ] ]) rank[ inx[i] ] = p;
else rank[ inx[i] ] = ++p;
Sa();
} Tnode p[maxn];
int size;
long long ans; bool Less(int loc) {
int cur = sa[loc];
for (int i = ; i < size; i++) {
if (d[cur] < p[i]) return true;
if (d[cur] > p[i]) return false;
cur++;
if (cur == n)
if (i == size - ) return false;
else return true;
}
return false;
} bool lessEqual(int loc) {
int cur = sa[loc];
for (int i = ; i < size; i++) {
if (d[cur] < p[i]) return true;
if (d[cur] > p[i]) return false;
cur++;
if (cur == n)
return true;
}
return true;
} int find() {
if (size == ) return n + ;
int i = , j = n - , mid;
while (i <= j) {
mid = (i + j) >> ;
if (Less(mid)) i = mid + ;
else j = mid - ;
}
int st = i;
i = , j = n - , mid;
while (i <= j) {
mid = (i + j) >> ;
if (lessEqual(mid)) i = mid + ;
else j = mid - ;
}
return i - st;
} void Solve() {
ans = ;
while (m--) {
scanf("%d", &size);
int pre, c;
scanf("%d", &pre);
for (int i = ; i < size - ; i++) {
scanf("%d", &c);
p[i] = Tnode(c / gcd(c, pre), pre / gcd(c, pre));
pre = c;
}
size--;
ans += find();
}
printf("%I64d\n", ans);
} int main() { int t;
scanf("%d", &t);
while (t--) {
Init();
Solve();
}
return ;
}
Funny Game
Time Limit: 2000/1000 MS
(Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 0 Accepted Submission(s): 0
Problem Description
Bob has an array {a1,a2,…,an}, each element is an integer between 1
and n. Bob also has m functions whose domain and codomain are
both {1,2,…,n}. Bob and Alice begin to play a game on
the array. Alice plays first. For each turn, the player can choose a function f and make every ai (1≤i≤n) become f(ai). For example, the array is {1,1,2,4,5} and f(1)=1,f(2)=3,f(3)=4,f(4)=1,f(5)=2. Then after the operation the array
will become {1,1,3,1,2}. If all the element in the array is same, then Alice
wins and the game stops. So you can see that Bob's goal is to stop Alice.
Suppose that both Alice and Bob play optimally. Alice wants to know if she can
always win no matter what the array looks like.
Input
There are multiple test cases. The first
line of input contains an integer T (1≤T≤200), indicating the number of test cases.
For each test case: The first line contains two integers n and m (1≤n,m≤100), indicating the element in the array
and the number of functions. In the next m lines, each contains n integers f(1),f(2),…,f(n) (1≤f(i)≤n,1≤i≤n).
Output
For each case, output "YES"(without
quotes) if Alice can always win no matter what the array looks like, otherwise
output "NO"(without quotes).
Sample Input
2
5 1
1 3 4 1 2
5 1
2 3 4 5 1
Sample Output
YES
NO
Funny Game
Time Limit: 2000/1000 MS
(Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 72 Accepted Submission(s): 2
问题描述
Bob有一个数组{a1,a2,…,an},数组中的每个元素都是介于1到n之间的整数。Bob还有m 个函数,他们的定义域和值域都是集合{1,2,…,n}。 Bob和Alice轮流开始玩游戏,Alice先开始。 对于每一轮,玩家可以选择一个函数f使得数组中每个元素 ai (1≤i≤n)变成f(ai)。例如,一开始数组是{1,1,2,4,5},有一个函数f(1)=1,f(2)=3,f(3)=4,f(4)=1,f(5)=2。那么经过一次操作,数组变为{1,1,3,1,2}。如果数组中的所有元素都相同(无论当前论是Bob还是Alice),那么Alice胜利游戏结束。然后Bob的目的是阻止Alice胜利。 假设Alice和Bob都足够聪明,每次都采取最优策略。问:无论数组的初始状态是什么,Alice是否都能够必胜?
输入描述
输入第一行包含一个整数T (1≤T≤200)表示测试数据组数。对于每组测试数据:第一行包含两个整数n和m (1≤n,m≤100)表示数组的大小和函数的个数。接下来m行,每行包含n个整数f(1),f(2),…,f(n) (1≤f(i)≤n,1≤i≤n)。
输出描述
对于每组数据,如果Alice一定能够必胜,输出YES,否则输出NO。
输入样例
2
5 1
1 3 4 1 2
5 1
2 3 4 5 1
输出样例
YES
NO
最后15分钟才看这题,一开始意思理解错了。。。。。悲剧!
看到这道题的第一感觉是博弈。。。可惜没时间做了,还有好像生疏了。/惨。
还有关键的一句话没理解;
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std; int f[][];
int flag[];
int father[]; int Find(int x) //找到x家族祖先并搜索路径上的成员都指向祖先
{
return x==father[x] ? x : father[x]=Find(father[x]);
} void Union(int a,int b) //b家族并入a家族,b祖先指向a祖先
{
if(a!=b)
father[b]=a;
} int main()
{
int T,n,m,i,j,k;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
memset(flag,,sizeof(flag)); for(i=;i<=n;i++)
father[i]=i; for(i=;i<=m;i++)
{
for(j=;j<=n;j++)
{
scanf("%d",&f[i][j]);
if(f[i][j]==j)
{
flag[j]++;
}
}
}
int cnt=;
for(k=;k<=n;k++)
{
// printf("%d\t",flag[k]);
if(flag[k]==m)
{
cnt++;
}
}
// printf("\ncnt=%d\n",cnt);
if(cnt==)
{
for(i=;i<=m;i++)
{
for(j=;j<=n;j++)
{
if(father[j]==j)
Union(Find(f[i][j]),Find(father[j])); //输入一组合并一组
// printf("%d",)
}
}
for(i=,k=;i<=n;i++)
{
// printf("father[%d]=%d\n",i,father[i]);
if(father[i]==i)k++; }
if(k==)
printf("YES\n");
else
printf("NO\n");
}
else
printf("NO\n");
}
return ;
}
/* 20
5 1
1 3 4 1 2
5 1
2 3 4 5 1
5 1
2 3 4 4 2
8 3
2 3 4 5 5 6 6 7
5 3 2 4 5 7 8 8
1 2 3 4 5 4 8 7
8 2
2 3 4 5 5 6 6 7
5 3 2 4 5 7 8 8 */
思路有问题,不要看喽。很搓!
大神做的:
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <queue>
#define Max(a, b) ((FASTBUFFER = ((a) - (b)) >> 31), ((b) & FASTBUFFER | (a) & ~FASTBUFFER))
#define Min(a, b) ((FASTBUFFER = ((a) - (b)) >> 31), ((a) & FASTBUFFER | (b) & ~FASTBUFFER))
#define Swap(a, b) (a ^= b, b ^= a, a ^= b)
#define OO 2147483647
#define priority_queue PQ
#define pb push_back
#define mp make_pair using namespace std; int FASTBUFFER; const int N = ; int test, n, m;
int f[N][N], ok[N][N], visit[N][N][], deg[N][N];
vector <pair <int, int> > e[N][N];
int hashCnt, hashNow[N][N];
queue <pair <pair <int, int>, int> > q; void work() {
scanf("%d %d", &n, &m);
for (int i = ; i <= m; i++) {
for (int j = ; j <= n; j++) {
scanf("%d", &f[i][j]);
}
} for (int i = ; i <= n; i++) {
for (int j = ; j <= n; j++) {
ok[i][j] = ;
for (int k = ; k <= m; k++) {
if (f[k][i] == f[k][j]) {
ok[i][j] = ;
break;
}
}
}
} for (int i = ; i <= n; i++) {
for (int j = i; j <= n; j++) {
deg[i][j] = ;
visit[i][j][] = ;
visit[i][j][] = ok[i][j];
e[i][j].clear();
}
} for (int i = ; i <= n; i++) {
for (int j = i; j <= n; j++) {
hashCnt++;
for (int k = ; k <= m; k++) {
int c = f[k][i], d = f[k][j];
int a = min(c, d), b = max(c, d);
if (hashNow[a][b] != hashCnt) {
hashNow[a][b] = hashCnt;
deg[i][j]++;
e[a][b].pb(mp(i, j));
}
}
}
} while (q.size()) {
q.pop();
} for (int i = ; i <= n; i++) {
for (int j = i; j <= n; j++) {
if (!deg[i][j]) {
q.push(mp(mp(i, j), ));
visit[i][j][] = ;
} if (ok[i][j]) {
q.push(mp(mp(i, j), ));
visit[i][j][] = ;
}
}
} while (q.size()) {
int a = q.front().first.first, b = q.front().first.second, c = q.front().second;
q.pop();
if (c == ) {
for (int x = ; x < (int)e[a][b].size(); x++) {
int a1 = e[a][b][x].first, b1 = e[a][b][x].second;
if (visit[a1][b1][] == ) {
visit[a1][b1][] = ;
q.push(mp(mp(a1, b1), ));
}
}
} else {
for (int x = ; x < (int)e[a][b].size(); x++) {
int a1 = e[a][b][x].first, b1 = e[a][b][x].second;
deg[a1][b1]--;
if (visit[a1][b1][] == && deg[a1][b1] == ) {
visit[a1][b1][] = ;
q.push(mp(mp(a1, b1), ));
}
}
}
} for (int i = ; i < n; i++) {
for (int j = i; j <= n; j++) {
if (visit[i][j][] == ) {
printf("NO\n");
return;
}
}
} printf("YES\n");
} int main() {
//freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout);
scanf("%d", &test);
while (test--) {
work();
} return ;
}
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<string>
#include<iostream>
#include<sstream>
#include<set>
#include<map>
#include<queue>
#include<bitset>
#include<vector>
#define SZ(X) ((int)(X).size())
#define ALL(X) (X).begin(), (X).end()
#define REP(I, N) for (int I = 0; I < (N); ++I)
#define REPP(I, A, B) for (int I = (A); I < (B); ++I)
#define RI(X) scanf("%d", &(X))
#define RII(X, Y) scanf("%d%d", &(X), &(Y))
#define RIII(X, Y, Z) scanf("%d%d%d", &(X), &(Y), &(Z))
#define DRI(X) int (X); scanf("%d", &X)
#define DRII(X, Y) int X, Y; scanf("%d%d", &X, &Y)
#define DRIII(X, Y, Z) int X, Y, Z; scanf("%d%d%d", &X, &Y, &Z)
#define RS(X) scanf("%s", (X))
#define CASET int ___T, case_n = 1; scanf("%d ", &___T); while (___T-- > 0)
#define MP make_pair
#define PB push_back
#define MS0(X) memset((X), 0, sizeof((X)))
#define MS1(X) memset((X), -1, sizeof((X)))
#define LEN(X) strlen(X)
#define F first
#define S second
typedef long long LL;
using namespace std;
const int MOD = 1e9+;
const int SIZE = ;
int a[SIZE],deg[SIZE*SIZE],used[SIZE][SIZE][];
int n,m,tt;
vector<int>e[SIZE*SIZE];
int get(int x,int y){
if(x>y)swap(x,y);
return x*n+y;
}
int main(){
CASET{
tt++;
RII(n,m);
REP(i,n*n)e[i].clear(),deg[i]=;
REP(i,m){
REP(j,n){
RI(a[j]);
a[j]--;
}
REP(j,n)REPP(k,j+,n){
e[get(a[j],a[k])].PB(get(j,k));
}
}
REP(i,n*n){
sort(ALL(e[i]));
e[i].resize(unique(ALL(e[i]))-e[i].begin());
if(i%n!=i/n)
REP(j,SZ(e[i]))deg[e[i][j]]++;
} queue<int>qq;
REP(i,n){
used[i][i][]=tt;
qq.push(i);
qq.push(i);
}
REP(i,n)REPP(j,i+,n){
int me=get(i,j);
if(deg[me]==){
used[i][j][]=tt;
qq.push(i);
qq.push(j);
}
}
while(!qq.empty()){
int x=qq.front();qq.pop();
int y=qq.front();qq.pop();
int me=get(x,y);
REP(i,SZ(e[me])){
int nx=e[me][i]/n;
int ny=e[me][i]%n;
if(used[nx][ny][]!=tt){
used[nx][ny][]=tt;
int you=get(nx,ny);
REP(j,SZ(e[you])){
int nnx=e[you][j]/n;
int nny=e[you][j]%n;
int he=get(nnx,nny);
deg[he]--;
if(!deg[he]){
qq.push(he/n);
qq.push(he%n);
used[he/n][he%n][]=tt;
}
}
}
}
}
bool lose=;
REP(i,n)REPP(j,i+,n){
if(used[i][j][]!=tt){
lose=;
}
}
if(lose)puts("NO");
else puts("YES");
}
return ;
}
官方解题报告:
1001 Jump and Jump... 首先算出每个人的成绩,然后sort一下就好了,考虑n的范围只有2或者3,只要用if+swap也是可行的。 1002 Taking Bus 简单的分类讨论,设s,x,y分别表示公交的始发站,起点和终点。大概有这样几种情况:1. s≤x<y, 2. x<s<y,3. x<y≤s, 4. s≤y<x, 5. y<s<x, 6. y<x≤s 分别写出公式即可。答案应该会超过int,注意要用long long。 1003 Matching on Array 首先我们考虑m=1的情况。给定两个数组A={a1,a2,…,an}和B={b1,b2,…,bk},问B在A中出现了几次。令ci=ai+1ai,1≤i<n,同样令di=bi+1bi,1≤i<k,那么上述问题可以转化为ci和di的模式匹配问题,这个正确性显然,也没有什么好证明的。于是对于m=1的情况只有用个kmp即可搞定。 现在考虑m>1的情况,我们考虑用ac自动机来做。考虑到字符集并不是普通的数字,而是一个分数,我们不放搞个分数类,然后用map存转移边。用m个模式串(Bob的序列)建好自动机之后,把文本串(Alice的序列)在自动机上跑一遍即可统计出答案。 1004 Funny Game 题目要求对于任何初始状态都要必胜,我们先把这个条件简化一下,毕竟我们不可能枚举所有的初始状态(总共n!个)。 我们先考虑{1,2,…,n}这个状态的必胜条件——对于任意一对数(x,y),1≤x,y≤n, Alice都能都把它们变成相同的数。这个条件也显然是充分必要的,随便想想就明白了。然后我们可以发现,如果{1,2,…,n}这个状态能够必胜的话,其他的状态也显然能够必胜。如果这个状态不能够必胜,那根本不需要考虑其他状态了。 于是我们只需要考虑是否对于任意一对数(x,y),1≤x,y≤n, Alice都能都把它们变成相同的数。这样的状态数只有O(n2)个,我们可以考虑dp来做。先用题目给定的m个函数构造出一张有向图,图中每个节点都是数对。仔细想想就会发现我们不能用普通的博弈思路来做,因为这个博弈会形成环,这时候我们考虑从终结状态往回推,得出每个状态的dp值。 令dp[i][j][0/1]表示数对为(i,j),Alice先(1)后(0)手是否必胜。然后我们知道dp[i][i][0/1]都是必胜的,并把这些状态放入队列。我们依次从队列中取出一个状态(x,y,turn),如果turn=1,那么这个状态的前驱是Bob的回合,不妨设为(a,b,0),那么如果(a,b,0)的后继状态都是Alice必胜的话,那么dp[a][b][0]显然也是Alice必胜的,否则这个状态的值我们目前无法确定。如果turn=0,类似的那么这个状态的前驱是Alice的回合,不妨设为(a,b,1),那么如果(a,b,1)的后继中有一个状态是Alice必胜的,那么dp[a][b][1]显然也是Alice必胜,考虑到(x,y,0)就是Alice必胜的,那么前驱状态(a,b,1)必然是Alice必胜。我们每次把必胜状态加入队列,用来更新那些未确定的状态。 最后统计是否每个(x,y,1)的状态都是必胜的,如果是那么Alice输出YES,否则输出NO。时间复杂度的话是O(n3)。
这几天状态不佳。要调整!
BestCoder Round #27的更多相关文章
- hdu5631 BestCoder Round #73 (div.2)
Rikka with Graph Accepts: 123 Submissions: 525 Time Limit: 2000/1000 MS (Java/Others) Memory Lim ...
- hdu5630 BestCoder Round #73 (div.2)
Rikka with Chess Accepts: 393 Submissions: 548 Time Limit: 2000/1000 MS (Java/Others) Memory Lim ...
- BestCoder Round #81 (div.2) 1004 String(动态规划)
题目链接:BestCoder Round #81 (div.2) 1003 String 题意 中文题,上有链接.就不贴了. 思路 枚举起点i,计算能够达到k个不同字母的最小下标j,则此时有子串len ...
- BestCoder Round #89 02单调队列优化dp
1.BestCoder Round #89 2.总结:4个题,只能做A.B,全都靠hack上分.. 01 HDU 5944 水 1.题意:一个字符串,求有多少组字符y,r,x的下标能组成等比数列 ...
- BestCoder Round #90 //div all 大混战 一题滚粗 阶梯博弈,树状数组,高斯消元
BestCoder Round #90 本次至少暴露出三个知识点爆炸.... A. zz题 按题意copy Init函数 然后统计就ok B. 博弈 题 不懂 推了半天的SG..... 结果这 ...
- bestcoder Round #7 前三题题解
BestCoder Round #7 Start Time : 2014-08-31 19:00:00 End Time : 2014-08-31 21:00:00Contest Type : ...
- Bestcoder round #65 && hdu 5593 ZYB's Tree 树形dp
Time Limit: 3000/1500 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submissio ...
- Bestcoder round #65 && hdu 5592 ZYB's Premutation 线段树
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submissio ...
- 暴力+降复杂度 BestCoder Round #39 1002 Mutiple
题目传送门 /* 设一个b[]来保存每一个a[]的质因数的id,从后往前每一次更新质因数的id, 若没有,默认加0,nlogn复杂度: 我用暴力竟然水过去了:) */ #include <cst ...
随机推荐
- Markdown的学习笔记一
之前学习看些书籍.学些技术都喜欢用xmind做思维导图的笔记,慢慢的发现想把一些笔记做的详细一些就会变得很复杂,个人觉得误了思维导图本意,而且用手机查看的时候也各种不方便.所以开始学习使用markdo ...
- Linq to xml修改CDATA节点值
增加节点时,我们是这样写的: xop.Document.Element("messages").Add( new XElement("message", new ...
- 基于GTK+3 开发远程控制管理软件(C语言实现)系列三 Windows7开发环境搭建
一.介绍与准备 考虑到目标客户端基本都是windows客户端,所以此次开发环境将搭建在windows7下,相关开发工具有Msys2 和 Eclipse For C/C++ Msys2 是msys的升级 ...
- GPS/轨迹追踪、轨迹回放、围栏控制
折腾一个多月终于弄完了这个项目,起初都未曾接触GPS/轨迹追踪.轨迹回放.圈划围栏...等一些在百度地图或者Googel地图操作的一些业务,后端的业务相对来说简单点 cas单点登录,mongdb灵活的 ...
- 自然语言处理(英文演讲)_2-gram
这里利用2-gram模型来提取一篇英文演讲的初略的主题句子,这里是英文演讲的的链接:http://pythonscraping.com/files/inaugurationSpeech.txt n-g ...
- JAVA框架之Hibernate【Hibernate缓存详解】
1.缓存介绍 Hibernate中提供了两级Cache,第一级别的缓存是Session级别的缓存,它是属于事务范围的缓存.这一级别的缓存由hibernate管理的,一般情况下无需进行干预:第二级别的缓 ...
- Microsoft Azure Storage架构分析
Microsoft云存储服务分为两个部分,SQL Azure和Azure Storage.云存储系统的可扩展性和功能不可兼得,必须牺牲一定的关系数据库功能换取可扩展性.Microsoft实现云存储的思 ...
- vue框架之自定义组件中使用v-model
通常 vue在html常见表单空间支持v-model双向绑定例如 <input v-model="message" placeholder="edit me&quo ...
- docker cgroup 技术之memory(首篇)
测试环境centos7 ,内核版本4.20 内核使用cgroup对进程进行分组,并限制进程资源和对进程进行跟踪.内核通过名为cgroupfs类型的虚拟文件系统来提供cgroup功能接口.cgroup有 ...
- HYPER-V的安装和双机调试的配置(一)
在上一篇文章中,我们已经安装好了VS2017以及WDK,现在我们就需要创建双机调试的环境, 因为本人的工作环境问题,不能使用WMWARE进行虚拟机的安装,因此就针对HYPER-V这个的虚拟机来进行双机 ...