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,bici (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[105];
int cmp(node x,node y)
{
    return x.mlen>y.mlen;
}
int ss[105];
int main()
{
    int T;
    int ans,i,j,n;
    int x,y,z;
    scanf("%d",&T);
    while(T--)
    {
        memset(a,0,sizeof(a));
        scanf("%d",&n);
        for(i=1;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+1,a+n+1,cmp);
        for(i=1;i<=n;i++)
            ss[a[i].id]=i;
        printf("%d",ss[1]);
        for(j=2;j<=n;j++)
            printf(" %d",ss[j]);
        printf("\n");

    }
    return 0;
}

 

 

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,yin,xiyi), which means i-th person is in bus station xi and wants goto bus station yi. (1≤im)

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),表示测试数据的组数。对于每组测试数据:第一行包含两个整数nm (2≤n,m≤105),表示公交车站的数目和乘客的数目。 接下来一行包含n−1个整数, d1,d2,…,dn−1 (1≤di≤109).  di表示第i个公交站和第i+1个公交站之间的距离。在接下来的m行, 每行包含两个整数xiyi (1≤xi,yin,xiyi), 表示第i个人时刻0的时候在第xi个公交站并且想要到第yi个公交站去。(1≤im)

 

对于第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[100005],lenf[100005],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[1]=0;
        lenf[n]=0;
        for(i=2;i<=n;i++)
        {
            scanf("%I64d",&len);
            lenz[i]=lenz[i-1]+len;
        }
        for(i=n-1;i>0;i--)
        {
            lenf[i]=lenz[n]-lenz[i];
        }
        int ss;
        len=0;
        for(i=1;i<=m;i++)
        {
            scanf("%d%d",&st,&et);
            ss=(i-1)%n+1;
            if(st==et) len=0;
            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[1]+lenz[n]-lenz[ss]+lenz[et];
                else
                    len=lenz[et]-lenz[ss];
            }
            printf("%I64d\n",len);
        }
    }
    return 0;
}

 

 

 

 

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的序列中出现的总次数是多少。

 

对于两个序列AB,如果A中有一个连续子序列在乘以某个缩放系数之后和B一样的话,那么BA中出现。

 

例如,A={2,4,8,16},B={1,2}, 那么BA中出现了3次。对应A中的子序列为{2,4}, {4,8}和{8,16},缩放系数分别是 0.5, 0.25和0.125。

输入描述

输入第一行包含一个整数T (1≤T≤30)表示测试数据组数。对于每组数据:

 

第一行包含两个整数nm  (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 = 300000 + 2;

struct Tnode {
    int a, b;
    Tnode (int c = 0, int d = 0) : 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 == 0) 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 = 0; i < m; i++) sum[i] = 0;
    for (i = 0; i < n; i++) sum[ x[i] = rank[i] ]++;
    for (i = 1; i < m; i++) sum[i] += sum[i - 1];
    for (i = n - 1; i > -1; i--) sa[ --sum[ x[i] ] ] = i;
    
    for (j = 1, p = 0; p < n; j <<= 1) {
        for (i = n - j, p = 0; i < n; i++) y[p++] = i;
        for (i = 0; i < n; i++)
            if (sa[i] >= j) y[p++] = sa[i] - j;
        
        for (i = 0; i < m; i++) sum[i] = 0;
        for (i = 0; i < n; i++) sum[ x[i] ]++;
        for (i = 1; i < m; i++) sum[i] += sum[i - 1];
        for (i = n - 1; i > -1; i--) sa[ --sum[ x[ y[i] ] ] ] = y[i];
        
        t = x; x = y; y = t;
        p = 1;
        x[ sa[0] ] = 0;
        for (i = 1; i < n; i++)
            if (equal(y, sa[i], sa[i - 1], j)) x[ sa[i] ] = p - 1;
            else x[ sa[i] ] = p++;
    }
    n--;
    for (i = 0; i < n; i++) sa[i] = sa[i + 1];
}

void Init() {
    scanf("%d%d", &n, &m);
    int pre = 0, c;
    scanf("%d", &pre);
    for (int i = 0; i < n - 1; i++) {
        scanf("%d", &c);
        d[i] = Tnode(c / gcd(pre, c), pre / gcd(pre, c));
        inx[i] = i;
        pre = c;
    }
    d[n - 1] = Tnode(0, 0);
    inx[n - 1] = n - 1;
    
    sort(inx, inx + n, cmp);
    
    int p = 0;
    rank[ inx[0] ] = p;
    for (int i = 1; i < n; i++) 
        if (d[ inx[i] ] == d[ inx[i - 1] ]) 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 = 0; i < size; i++) {
        if (d[cur] < p[i]) return true;
        if (d[cur] > p[i]) return false;
        cur++;
        if (cur == n) 
            if (i == size - 1) return false;
            else return true;
    }
    return false;
}

bool lessEqual(int loc) {
    int cur = sa[loc];
    for (int i = 0; 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 == 0) return n + 1;
    int i = 0, j = n - 1, mid;
    while (i <= j) {
        mid = (i + j) >> 1;
        if (Less(mid)) i = mid + 1;
        else j = mid - 1;
    }
    int st = i;
    i = 0, j = n - 1, mid;
    while (i <= j) {
        mid = (i + j) >> 1;
        if (lessEqual(mid)) i = mid + 1;
        else j = mid - 1;
    }
    return i - st;
}

void Solve() {
    ans = 0;
    while (m--) {
        scanf("%d", &size);
        int pre, c;
        scanf("%d", &pre);
        for (int i = 0; i < size - 1; 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 0;
}
View Code

 

 

 

 

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≤in) 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≤in).

 

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≤in)变成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)表示测试数据组数。对于每组测试数据:第一行包含两个整数nm (1≤n,m≤100)表示数组的大小和函数的个数。接下来m行,每行包含n个整数f(1),f(2),…,f(n) (1≤f(i)≤n,1≤in)。

输出描述

对于每组数据,如果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[105][105];
int flag[105];
int father[105];

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,0,sizeof(flag));

        for(i=0;i<=n;i++)
            father[i]=i;

        for(i=1;i<=m;i++)
        {
            for(j=1;j<=n;j++)
            {
                scanf("%d",&f[i][j]);
                if(f[i][j]==j)
                {
                    flag[j]++;
                }
            }
        }
        int cnt=0;
        for(k=1;k<=n;k++)
        {
  //          printf("%d\t",flag[k]);
            if(flag[k]==m)
            {
                cnt++;
            }
        }
 //       printf("\ncnt=%d\n",cnt);
        if(cnt==1)
        {
            for(i=1;i<=m;i++)
            {
                for(j=1;j<=n;j++)
                {
                    if(father[j]==j)
                        Union(Find(f[i][j]),Find(father[j]));  //输入一组合并一组
 //                   printf("%d",)
                }
            }
            for(i=1,k=0;i<=n;i++)
            {
     //           printf("father[%d]=%d\n",i,father[i]);
                if(father[i]==i)k++;

            }
            if(k==1)
                printf("YES\n");
            else
                printf("NO\n");
        }
        else
            printf("NO\n");
    }
    return 0;
}
/*

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

*/
View Code

思路有问题,不要看喽。很搓!

 

大神做的:

#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 = 105;

int test, n, m;
int f[N][N], ok[N][N], visit[N][N][2], 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 = 1; i <= m; i++) {
        for (int j = 1; j <= n; j++) {
            scanf("%d", &f[i][j]);
        }
    }
    
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            ok[i][j] = 0;
            for (int k = 1; k <= m; k++) {
                if (f[k][i] == f[k][j]) {
                    ok[i][j] = 1;
                    break;
                }
            }
        }
    }
    
    for (int i = 1; i <= n; i++) {
        for (int j = i; j <= n; j++) {
            deg[i][j] = 0;
            visit[i][j][0] = 0;
            visit[i][j][1] = ok[i][j];
            e[i][j].clear();
        }
    }
    
    for (int i = 1; i <= n; i++) {
        for (int j = i; j <= n; j++) {
            hashCnt++;
            for (int k = 1; 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 = 1; i <= n; i++) {
        for (int j = i; j <= n; j++) {
            if (!deg[i][j]) {
                q.push(mp(mp(i, j), 0));
                visit[i][j][0] = 1;
            }
            
            if (ok[i][j]) {
                q.push(mp(mp(i, j), 1));
                visit[i][j][1] = 1;
            }
        }
    }
    
    while (q.size()) {
        int a = q.front().first.first, b = q.front().first.second, c = q.front().second;
        q.pop();
        if (c == 0) {
            for (int x = 0; x < (int)e[a][b].size(); x++) {
                int a1 = e[a][b][x].first, b1 = e[a][b][x].second;
                if (visit[a1][b1][1] == 0) {
                    visit[a1][b1][1] = 1;
                    q.push(mp(mp(a1, b1), 1));
                }
            }
        } else {
            for (int x = 0; 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][0] == 0 && deg[a1][b1] == 0) {
                    visit[a1][b1][0] = 1;
                    q.push(mp(mp(a1, b1), 0));
                }
            }
        }
    }
    
    for (int i = 1; i < n; i++) {
        for (int j = i; j <= n; j++) {
            if (visit[i][j][1] == 0) {
                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 0;
}
View Code
#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+7;
const int SIZE = 100;
int a[SIZE],deg[SIZE*SIZE],used[SIZE][SIZE][2];
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]=0;
        REP(i,m){
            REP(j,n){
                RI(a[j]);
                a[j]--;
            }
            REP(j,n)REPP(k,j+1,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][0]=tt;
            qq.push(i);
            qq.push(i);
        }
        REP(i,n)REPP(j,i+1,n){
            int me=get(i,j);
            if(deg[me]==0){
                used[i][j][0]=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][1]!=tt){
                    used[nx][ny][1]=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][0]=tt;
                        }
                    }
                }
            }
        }
        bool lose=0;
        REP(i,n)REPP(j,i+1,n){
            if(used[i][j][1]!=tt){
                lose=1;
            }
        }
        if(lose)puts("NO");
        else puts("YES");
    }
    return 0;
}
View Code

 

 

官方解题报告:

1001 Jump and Jump...

首先算出每个人的成绩,然后sort一下就好了,考虑n的范围只有2或者3,只要用if+swap也是可行的。

1002 Taking Bus

简单的分类讨论,设s,x,y分别表示公交的始发站,起点和终点。大概有这样几种情况:1. sx<y, 2. x<s<y,3. x<ys, 4. sy<x, 5. y<s<x, 6. y<xs

分别写出公式即可。答案应该会超过int,注意要用long long。

1003 Matching on Array

首先我们考虑m=1的情况。给定两个数组A={a1,a2,,an}B={b1,b2,,bk},问BA中出现了几次。令ci=ai+1ai,1i<n,同样令di=bi+1bi,1i<k,那么上述问题可以转化为cidi的模式匹配问题,这个正确性显然,也没有什么好证明的。于是对于m=1的情况只有用个kmp即可搞定。

现在考虑m>1的情况,我们考虑用ac自动机来做。考虑到字符集并不是普通的数字,而是一个分数,我们不放搞个分数类,然后用map存转移边。用m个模式串(Bob的序列)建好自动机之后,把文本串(Alice的序列)在自动机上跑一遍即可统计出答案。

1004 Funny Game

题目要求对于任何初始状态都要必胜,我们先把这个条件简化一下,毕竟我们不可能枚举所有的初始状态(总共n!个)。

我们先考虑{1,2,,n}这个状态的必胜条件——对于任意一对数(x,y),1x,yn, Alice都能都把它们变成相同的数。这个条件也显然是充分必要的,随便想想就明白了。然后我们可以发现,如果{1,2,,n}这个状态能够必胜的话,其他的状态也显然能够必胜。如果这个状态不能够必胜,那根本不需要考虑其他状态了。

于是我们只需要考虑是否对于任意一对数(x,y),1x,yn, 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)

这几天状态不佳。要调整!

 

posted @ 2015-01-25 22:30  寻找&星空の孩子  阅读(378)  评论(0编辑  收藏  举报