浙江省賽部分題解

Sequence in the Pocket

DreamGrid has just found an integer sequence  in his right pocket. As DreamGrid is bored, he decides to play with the sequence. He can perform the following operation any number of times (including zero time): select an element and move it to the beginning of the sequence.

What's the minimum number of operations needed to make the sequence non-decreasing?

Input

There are multiple test cases. The first line of the input contains an integer , indicating the number of test cases. For each test case:

The first line contains an integer  (), indicating the length of the sequence.

The second line contains  integers  (), indicating the given sequence.

It's guaranteed that the sum of  of all test cases will not exceed .

Output

For each test case output one line containing one integer, indicating the answer.

Sample Input

2
4
1 3 2 4
5
2 3 3 5 5

Sample Output

2
0

Hint

For the first sample test case, move the 3rd element to the front (so the sequence become {2, 1, 3, 4}), then move the 2nd element to the front (so the sequence become {1, 2, 3, 4}). Now the sequence is non-decreasing.

For the second sample test case, as the sequence is already sorted, no operation is needed.

題意:可以把每個點放到隊列的最前面,問最少用多少次操作可以把這個序列變成非遞減序列?

給出的是無序序列,我們把這個隊列排一次序,因爲如果有點在這個排過序的序列中的相對順序和原序列一樣,就說明這些點是不用換的,這樣就可以求出有多少個點需要操作了......awsl

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int a[N],n,b[N];
int main()
{
    int t;
    while(~scanf("%d",&t)){
        while(t--){
            scanf("%d",&n);
            for(int i=1;i<=n;i++){
                scanf("%d",&a[i]);
                b[i]=a[i];
            }
            sort(a+1,a+1+n);
            int j=n;
            for(int i=n;i>=1;i--){
                if(a[j]==b[i])
                    j--;
            }
            printf("%d\n",j);
        }
    }
}

Singing Everywhere

Baobao loves singing very much and he really enjoys a game called Singing Everywhere, which allows players to sing and scores the players according to their performance.

Consider the song performed by Baobao as an integer sequence , where  indicates the -th note in the song. We say a note  is a "voice crack" if ,  and . The more voice cracks BaoBao sings, the lower score he gets.

To get a higher score, BaoBao decides to delete at most one note in the song. What's the minimum number of times BaoBao sings a voice crack after this operation?

Input

There are multiple test cases. The first line of the input contains an integer  (about 100), indicating the number of test cases. For each test case:

The first line contains one integer  (), indicating the length of the song.

The second line contains  integers  (), indicating the song performed by BaoBao.

It's guaranteed that at most 5 test cases have .

Output

For each test case output one line containing one integer, indicating the answer.

Sample Input

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

Sample Output

1
0
2

Hint

For the first sample test case, BaoBao does not need to delete a note. Because if he deletes no note, he will sing 1 voice crack (the 4th note), and no matter which note he deletes, he will also always sing 1 voice crack.

For the second sample test case, BaoBao can delete the 3rd note, and no voice cracks will be performed. Yay!

For the third sample test case, BaoBao can delete the 4th note, so that only 2 voice cracks will be performed (4 8 3 and 3 6 4).

題意:問可以刪除一個點,使這個序列中一個數比前面的數大並且比後面的數也大的數最少?

只有當相隔1的兩個點都是這種點並且相等的時候纔可以刪除他倆間的那個點,使得一下減2,其餘可以分別判斷符合條件的點鐘刪除它或者他前面或它後面的點。

就是判斷有點多,需要仔細,但還是一遍就寫過了......

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int a[N],n;
bool vis[N];
int main()
{
    int t;
    while(~scanf("%d",&t)){
        while(t--){
                memset(a,0,sizeof(a));
                int ans=0;
            scanf("%d",&n);
            memset(vis,false,sizeof(vis));
            for(int i=1;i<=n;i++)
                scanf("%d",&a[i]);
            for(int i=2;i<n;i++)
                if(a[i]>a[i-1]&&a[i]>a[i+1])
                   ans++,vis[i]=1;
        bool flag=false;
        bool flag2=false;
            for(int i=2;i<n;i++){
                if(a[i]==a[i+2]&&vis[i]&&vis[i+2]){
                    flag=true;
                    printf("%d\n",ans-2);
                    break;
                }
                else if(!(a[i]>a[i-2]&&a[i]>a[i+1])&&vis[i])
                    flag2=true;
                else if(!(a[i]>a[i+2]&&a[i]>a[i-2])&&vis[i])
                    flag2=true;
                else {
                    if(vis[i]){
                        if(i==2){
                            if(!(a[i+1]>a[i-1]&&a[i+1]>a[i+2]))
                                flag2=true;
                        }
                        else if(i==n-1){
                            if(!(a[i-1]>a[i-2]&&a[i-1]>a[i+1]))
                                flag2=true;
                        }
                        else {
                            if(!(a[i+1]>a[i-1]&&a[i+1]>a[i+2])&&!(a[i-1]>a[i-2]&&a[i-1]>a[i+1]))
                                flag2=true;
                        }
                    }
                }
            }
            if(flag)
                continue;
            else if(flag2)
                printf("%d\n",ans-1);
            else printf("%d\n",ans);
        }
    }
}

Welcome Party

The 44th World Finals of the International Collegiate Programming Contest (ICPC 2020) will be held in Moscow, Russia. To celebrate this annual event for the best competitive programmers around the world, it is decided to host a welcome party for all  participants of the World Finals, numbered from  to  for convenience.

The party will be held in a large hall. For security reasons, all participants must present their badge to the staff and pass a security check in order to be admitted into the hall. Due to the lack of equipment to perform the security check, it is decided to open only one entrance to the hall, and therefore only one person can enter the hall at a time.

Some participants are friends with each other. There are  pairs of mutual friendship relations. Needless to say, parties are more fun with friends. When a participant enters the hall, if he or she finds that none of his or her friends is in the hall, then that participant will be unhappy, even if his or her friends will be in the hall later. So, one big problem for the organizer is the order according to which participants enter the hall, as this will determine the number of unhappy participants. You are asked to find an order that minimizes the number of unhappy participants. Because participants with smaller numbers are more important (for example the ICPC director may get the number 1), if there are multiple such orders, you need to find the lexicographically smallest one, so that important participants enter the hall first.

Please note that if participant  and  are friends, and if participant  and  are friends, it's NOT necessary that participant  and  are friends.

Input

There are multiple test cases. The first line of the input contains a positive integer , indicating the number of cases. For each test case:

The first line contains two integers  and  (), the number of participants and the number of friendship relations.

The following  lines each contains two integers  and  (), indicating that the -th and the -th participant are friends. Each friendship pair is only described once in the input.

It is guaranteed that neither the sum of  nor the sum of  of all cases will exceed .

Output

For each case, print a single integer on the first line, indicating the minimum number of unhappy participants. On the second line, print a permutation of  to  separated by a space, indicating the lexicographically smallest ordering of participants entering the hall that achieves this minimum number.

Consider two orderings  and , we say  is lexicographically smaller than , if there exists an integer  (), such that  holds for all , and .

Please, DO NOT output extra spaces at the end of each line, or your solution may be considered incorrect!

Sample Input

2
4 3
1 2
1 3
1 4
4 2
1 2
3 4

Sample Output

1
1 2 3 4
2
1 2 3 4

 

這個題當時察覺到用BFS了,但當時腦子可能轉不動了,,第二天寫了第二發就過了......

因爲要使不高興的最少,但肯定會有不高興的,所以用並查集找聯通塊,並且處理的時候要讓小的點當父節點,然後把根節點放入優先隊列中,在進行BFS再把與隊首的點相連的點也加進有點隊列中,一直這樣操作就好......

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
vector<int>v[N];
int pre[N],n,m;
bool vis[N];
priority_queue<int,vector<int>,greater<int> >q;
int Find(int x)
{
   return pre[x]==x?x:Find(pre[x]);
}
void join(int x,int y)
{
    int fx=Find(x);
    int fy=Find(y);
    if(fx!=fy){
        if(fx<fy)
        pre[fy]=fx;
    else pre[fx]=fy;
    }
}
void bfs()
{
    int num=0;
    while(!q.empty()){
        int p=q.top();
        q.pop();
         num++;
         if(num==n)
        printf("%d",p);
        else printf("%d ",p);
        for(int i=0;i<v[p].size();i++){
            int k=v[p][i];
            if(!vis[k]){
                vis[k]=1;
                q.push(k);
            }
        }
    }
}
int main()
{
    int t;
    while(~scanf("%d",&t)){
        while(t--){
                while(!q.empty())
                q.pop();
                for(int i=1;i<=n;i++)
                    v[i].clear();
            scanf("%d%d",&n,&m);
            for(int i=1;i<=n;i++)
                pre[i]=i;
            memset(vis,0,sizeof(vis));
            int x,y;
            for(int i=1;i<=m;i++){
                scanf("%d%d",&x,&y);
                v[x].push_back(y);
                v[y].push_back(x);
                join(x,y);
            }
            int ans=0;
            for(int i=1;i<=n;i++){
                    int c=Find(i);
                if(vis[c]==0){   //根節點
                        ans++;
                    vis[c]=1;
                    q.push(i);
                }
            }
            printf("%d\n",ans);
            bfs();
            printf("\n");
        }
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章