1. 程式人生 > >Codeforces Round #346 (Div. 2) (659A,659B,659C,659D(幾何叉乘),659E(並查集))

Codeforces Round #346 (Div. 2) (659A,659B,659C,659D(幾何叉乘),659E(並查集))

Round House

題目連結:

解題思路:

The answer for the problem is calculated with a formula ((a - 1 + b)  n + n n + 1.

Such solution has complexity O(1).

There is also a solution with iterations, modelling every of |b|'s Vasya's moves by one entrance one by one in desired direction, allowed to pass all the tests.

This solution's complexity is O(|b|).


AC程式碼:

#include <bits/stdc++.h>
using namespace std;

int main(){
    int n,a,b;
    while(~scanf("%d%d%d",&n,&a,&b)){
        int ans = (a+b)%n;
        if(ans < 0)
            ans += n;
        if(ans == 0)
            ans = n;
        printf("%d\n",ans);
    }
    return 0;
}

Qualifying Contest

題目連結:

解題思路:

Let's consider the participants from every region separately. So for every region we just need to sort all of its participants by their score in non-increasing order. The answer for a region is inconsistent if and only if the score of the second and the third participant in this order are equal, otherwise the answer is the first and the second participant in this order.

The solution complexity is .


AC程式碼:

#include <bits/stdc++.h>
using namespace std;

struct node{
    string name;
    int score;
    node(string _name,int _score){
        name = _name;
        score = _score;
    }
};
int vis[10005];
vector<node> no[10005];

bool cmp(node a,node b){
    return a.score > b.score;
}

int main(){
    int n,m;
    while(~scanf("%d%d",&n,&m)){
        for(int i = 0; i <= m; i++)
            no[i].clear();
        string name;
        int region,score;
        for(int i = 0; i < n; i++){
            cin>>name>>region>>score;
            no[region].push_back(node(name,score));
        }
        for(int i = 1; i <= m; i++){
            sort(no[i].begin(),no[i].end(),cmp);
            int len = no[i].size();
            if(len > 2 && no[i][1].score == no[i][2].score)
                puts("?");
            else
                cout<<no[i][0].name<<" "<<no[i][1].name<<endl;
        }
    }
    return 0;
}

Tanya and Toys

題目連結:

解題思路:

Our task is to take largest amount of toys Tanya doesn't have yet the way the sum of their costs doesn't exceed m. To do that one can perform greedy algorithm: let's buy the cheepest toy Tanya doesn't have at every step, while the amount of money left are sufficient to do that. The boolean array used can be a handle in that, storing true values in indices equal to toy types which Tanya does have at the moment. As soon as 109 money is sufficient to buy no more than 105 toys used is enough to be sized 2 × 105(we won't buy the toys with types numbered greater). So we just need to iterate over the number of type we want to buy, and if corresponding value in used is equal to false, we should buy it, otherwise we can't.

The solution complexity is .

One can use the <> data structure (C++ \texttt{std::set}, for example), for storing the types Tanya has at the moment. In this case the complexity is .


AC程式碼:

#include <bits/stdc++.h>
using namespace std;

vector<int> v;
map<int,int> ma;

int main(){
    int n,m;
    while(~scanf("%d%d",&n,&m)){
        ma.clear();
        v.clear();
        int x;
        for(int i = 0; i < n; ++i){
            scanf("%d",&x);
            ma[x]++;
        }
        for(int i = 1; i <= 1000000; ++i){
            if(i > m)
                break;
            if(!ma[i]){
                v.push_back(i);
                m -= i;
            }
        }
        int len = v.size();
        printf("%d\n",len);
        if(len){
            for(int i = 0; i < len-1; ++i)
                printf("%d ",v[i]);
            printf("%d\n",v[len-1]);
        }
    }
    return 0;
}


Bicycle Race

題目連結:

解題思路:

From the track description follows that Maria moves the way that the water always located to the right from her, so she could fall into the water only while turning left. To check if the turn is to the left, let's give every Maria's moves directions a number: moving to the north —0, moving to the west — 1, to the south — 2 and to the east — 3. Then the turn is to the left if and only if the number of direction after performing a turn dir is equal to the number before performing a turn oldDir plus one modulo 4 .

This solution has complexity O(n).

One can solve this problem in alternative way. Let the answer be equal to x (that means that the number of inner corners of 270degrees equals x, but the number of inner corners of 90 degrees to n - x). As soon as the sum of the inner corners' values of polygon ofn vertices is equal to 180 × (n - 2), then x × 270 + (n - x) × 90 equals to 180 × (n - 2). This leads us to , being the answer for the problem calculated in O(1).


AC程式碼:

#include <bits/stdc++.h>
using namespace std;

struct Point{
    int x,y;
    Point(int x=0,int y=0):x(x),y(y){} // 建構函式,方便程式碼編寫
}po[1005];
typedef Point Vector;  //從程式實現上,Vector只是Point的別名

//點-點=向量
Vector operator - (Vector A,Vector B){
    return Vector(A.x-B.x,A.y-B.y);
}

int Cross(Vector A,Vector B){
    return A.x*B.y-A.y*B.x;
}

int main(){
    int n;
    while(~scanf("%d",&n)){
        for(int i = 0; i <= n; ++i)
            scanf("%d%d",&po[i].x,&po[i].y);
        int ans = 0;
        for(int i = 2; i <= n; ++i){
            if(Cross(po[i]-po[i-1],po[i-1]-po[i-2]) < 0)//逆時針的角
                ans++;
        }
        printf("%d\n",ans);
    }
    return 0;
}

New Reform

題目連結:

解題思路:

One should notice, that for every connected component of the graph the problem could be solved independently, so we just need to solve the problem for any connected graph.

Let this connected graph (of n vertices) contain n - 1 edge (such is called a tree). If one maintain a DFS from any of its vertex, every edge will be oriented, and each of them could given to its ending vertex, this way every vertex (except the one we launched DFS from, that is the root) will be satisfied by an edge. In this case the answer is equal to 1.

Let's then deal with a case when the graph contains more than n - 1 edges. This graph contains at least one cycle. Let's take arbitrary vertex from any of the cycles and launch a DFS (as above) from it. All vertices except chosen will be satisfied, so we are to give an edge to the chosen vertex. As soon as chosen vertex belongs to a cycle, at least one of its edge will not be taken to account in the DFS, so it can be given to a root. This way all the vertices will be satisfied.

Now we are able to solve the task for any connected graph, so we are to divide the graph into a connected components — this can be easily done by DFS or BFS.

The solution complexity is O(n + m).


AC程式碼:

#include <bits/stdc++.h>
using namespace std;

const int N = 100005;
int fa[N],tot[N],TOT[N];

int findset(int x){
    if(fa[x] == x)
        return fa[x];
    return fa[x] = findset(fa[x]);
}

int main(){
    int n,m;
    while(~scanf("%d%d",&n,&m)){
        memset(tot,0,sizeof(tot));
        memset(TOT,0,sizeof(TOT));
        for(int i = 1; i <= n; ++i){
            fa[i] = i;
            tot[i] = 1;
            TOT[i] = 0;
        }
        int u,v;
        for(int i = 1; i <= m; ++i){
            scanf("%d%d",&u,&v);
            u = findset(u),v = findset(v);
            if(u == v)
                TOT[u]++;
            else{
                fa[u] = v;
                tot[v] += tot[u];
                TOT[v] += TOT[u] + 1;
                tot[u] = TOT[u] = 0;
            }
        }
        int ans = 0;
        for(int i = 1; i <= n; ++i){
            findset(i);
            if(fa[i] == i)
                ans += tot[i] > TOT[i]? 1 : 0;
        }
        printf("%d\n", ans);
    }
	return 0;
}