2019年ICPC浙江省省賽 (solve9/13)

A題看博客鏈接:https://blog.csdn.net/qq_38185591/article/details/90031185

B: Element Swapping (數學 + 思維)


Time Limit: 1 Second      Memory Limit: 65536 KB


DreamGrid has an integer sequence  and he likes it very much. Unfortunately, his naughty roommate BaoBao swapped two elements  and  () in the sequence when DreamGrid wasn't at home. When DreamGrid comes back, he finds with dismay that his precious sequence has been changed into !

What's worse is that DreamGrid cannot remember his precious sequence. What he only remembers are the two values

Given the sequence after swapping and the two values DreamGrid remembers, please help DreamGrid count the number of possible element pairs  BaoBao swaps.

 

Note that as DreamGrid is poor at memorizing numbers, the value of  or  might not match the sequence, and no possible element pair can be found in this situation.

Two element pairs  () and  () are considered different if  or .

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 three integers ,  and  (), indicating the length of the sequence and the two values DreamGrid remembers.

The second line contains  integers  (), indicating the sequence after swapping. It's guaranteed that  and .

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 number of possible element pairs BaoBao swaps.

Sample Input

2
6 61 237
1 1 4 5 1 4
3 20190429 92409102
1 2 3

Sample Output

2
0

Hint

For the first sample test case, it’s possible that BaoBao swaps the 2nd and the 3rd element, or the 5th and the 6th element.

題意和思路:

給出x和y(x和y的定義上面都給出了,給出的x和y是原來序列的),並且b序列,給出的b序列有兩個元素產生了交換,問你有多少種交換方法,我們可以先把先現在序列的x和y求出來,假設x1 y1

原來序列是a b c

現在序列是a c b

可以對(y1 - y) / (x1 - x)推導一下可以得到等於(b+c),即是交換兩個元素的和

再考慮除數是0的情況,(x1 - x) ==  0,如果(y1 - y)不等於0的話,那肯定是無解的,如果(y1 - y) == 0,例如

5 15 15

1 1 1 1 1  這種情況,應該是由相同數交換的,所以結果方案數就是(5 * 4) / 2;

再來看,(y1 - y) % (x1 - x) != 0的時候也無解的 

現在有了b+c,來算結果,注意並不是所有的a[i] +a[j] == sum && (i != j)都可以組成的(因爲起始我是這麼想的,所以wa半天)

我們可以假設一下當前位置i,然後得到差sum - a[i]

首先如果a[i] == cha 這個肯定是不作爲結果的,假設滿足的位置是i + id位置 (x1 - x)  = (id) * (cha - a[i]),可以得到id,然後判斷是否越界,再計數答案就可以了。

代碼:

ll n,k,m;
ll a[maxn];
map<int,int>vis;
int main() {
    string str1,str2;int t;
    cin >> t;
    while(t--){
        ll x,y;
        vis.clear();
        scanf("%lld%lld%lld",&n,&x,&y);
        for(int i = 1;i <= n;i++) scanf("%lld",&a[i]),vis[a[i]]++;
        ll x1 = 0,y1 = 0;
        for(ll i = 1;i <= n;i++){
            x1 += i * a[i];
            y1 += i * a[i] * a[i];;
        }

        if(((x1 - x) == 0 && (y1 - y) != 0 ) ){
                printf("0\n");
            continue;
        }
        ll ans = 0;
        if(x1 - x == 0){
            for(int i = 1;i <= n;i++){
                ll num = vis[a[i]];
                ans += num * (num - 1) / 2;
                vis[a[i]] = 0;
            }
           printf("%lld\n",ans);
           continue;
        }
        if((y1 - y) % (x1 - x)){
            printf("0\n");
            continue;
        }
        ll sum = (y1 - y) / (x1 - x);
        for(int i = 1;i <= n;i++){
                ll cha = sum - a[i];
                if(cha == a[i]) continue;
                int id = (x1 - x) / (cha - a[i]);
//                cout << id << endl;
                if(i + id > n || i + id <= i) continue;
                if(a[id + i] == cha) ans++;
        }
           printf("%lld\n",ans);
//        cout << sum << endl;
    }
}

 

E:Sequence in the Pocket


Time Limit: 2 Seconds      Memory Limit: 65536 KB


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.

題意和思路:

給定一個數組,然後每次可以從任意位置拿出來這個數,放在最前面,問最少需要多少次操作,使得這個數組是非遞減的

做過很多次的題了,其實本質就是最後的一些數,已經放好了幾個了,比如樣例 

1 3 2 4 

1 2 3 4

3和4已經放好了,其他的數不管怎麼樣都要移動,所以就是n - 放好的數

排序掃一下就可以了

代碼:

int a[maxn],b[maxn];
int n;
int main() {
    int t;
    cin >> t;
    while(t--){
        scanf("%d",&n);
        for(int i = 1;i <= n;i++) cin >>a[i];
        for(int i = 1;i <= n;i++) b[i] = a[i];
        sort(b + 1,b + 1 + n); int cnt = 0;
        for(int i = n,j = n;i >= 1;i--){
            if(a[i] == b[j]) j--,cnt++;
        }
        cout << n - cnt <<endl;
    }
}

FGHI (略掉吧,因爲實在比較簡單)

H 只能修改一個數,那最多隻能影響兩個噪音,對每個位置都判斷一下,往左和往右是不是刪除了都影響就可以了

    cin >> t;
    while(t--){
        scanf("%d",&n);
        for(int i = 0;i <= n + 30;i++) a[i] =  INF;
        for(int i = 1;i <= n;i++)  scanf("%d",&a[i]);
        int cnt = 0;
        for(int i = 2;i < n;i++){
            if(a[i] > a[i - 1] && a[i] > a[i + 1]) cnt++;
        }
        int num = 0;
//        cout << cnt << endl;
        for(int i = 2;i <= n - 2;i++){
            if(a[i] > a[i - 1] && a[i] > a[i + 1] && a[i + 2] > a[i + 3] && a[i + 2] > a[i + 1]){
                if(a[i] == a[i + 2]){
                        num = max(num,2);
                    break;
                }else{
                        num = max(num,1);
                    break;
                }
            }
        }
        cout << cnt - num << endl;

    }

I就是可以看出fib的奇偶性是11011011,有九種情況判斷一下就可以

        for(int i = 0;i< str1.size();i++){
            s1 += (str1[i] - '0');
        }
        for(int i = 0;i< str2.size();i++){
            s2 += (str2[i] - '0');
        }
        int flag1 ,flag2 ; 
        s1 %= 3,s2 %= 3;
        if(!s1 && !s2){
            cout << 0 << endl;
        }else if(!s1 && s2 == 1)
            cout << 1 << endl;
         else if(!s1 && s2 == 2)
            cout << 0 << endl;
         else if(s1 == 1 && s2 == 2)
            cout << 0 << endl;
         else if(s1 == 1 && s2 == 1)
            cout << 1 << endl;
         else if(s1 == 1 && s2 == 0)
            cout << 0 << endl;
        else if(s1 == 2 && s2 == 0)
            cout << 1 << endl;
        else if(s1 == 2 && s2 == 1)
            cout << 0 << endl;
        else if(s1 == 2 && s2 == 2)
            cout << 1 << endl;

J:Welcome Party


Time Limit: 2 Seconds      Memory Limit: 131072 KB


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

題意和思路:

n個人和m個友誼關係,但是不傳遞,每次一個人如果沒有朋友在大廳裏,進大廳會增加一點貢獻,問你最小的貢獻是多少,並且輸出進大廳的順序,要求字典序最小

DSU+優先隊列bfs,對於每個塊先並查集合並起來,合併的時候處理一下,把小的點當做頂點,然後把頂點放個優先隊列,直接bfs輸出序列就可以。(md,不知道爲什麼把vector開成vector<vector<int> > 就一直蜜汁段錯誤,調了一個小時,氣死,還有就是日了狗,並查集不能用遞歸的,卡了棧的大小)

代碼:


int fa[maxn];
//int Find(int x) {   if(x != fa[x]) return fa[x] = Find(fa[x]);  return fa[x];}
int Find(int x) {
   	int p=x;
	while(p!=fa[p])
		p=fa[p];
	while(x!=fa[x]){
		x=fa[x];
		fa[x]=p;
	}
	return p;
}
bool vis[maxn];
int n,m;
vector<int >v[maxn];
priority_queue<int,vector<int>,greater<int> >q;
void bfs()
{
    while(!q.empty()) q.pop();
    int num = 0;
    for(int i = 1;i <= n;i++){
        if(fa[i] == i) q.push(i),num++;
    }
    printf("%d\n",num);
    vector<int>ans;
    int cnt = 0;
    while(!q.empty()){
        int x = q.top();
        q.pop();
        if(vis[x]) continue;
        ans.push_back(x);vis[x] = 1; cnt++;
//        if(cnt >= n) break;
        for(auto d:v[x]){
            if(!vis[d]){
                q.push(d);
            }
        }
    }
    for(int i = 0;i < ans.size() - 1;i++){
         printf("%d ",ans[i]);
    }
    printf("%d\n",ans[ans.size() - 1]);
}
int main() {
    int t;
    cin >> t;
    while(t--){
        scanf("%d%d",&n,&m);
        for(int i = 0;i <= n;i++)fa[i] = i,vis[i] = 0,v[i].clear();
        for(int i = 1;i <= m;i++){
                int a,b;
            scanf("%d%d",&a,&b);
             v[a].pb(b);
             v[b].pb(a);
            int x = Find(a);
            int y = Find(b);
            if(x > y) fa[x] = y;
            else fa[y] = x;
        }
        for(int i = 1;i <= n;i++) fa[i] = Find(i);
        bfs();

    }
    return 0;
}

 

K:Welcome Party


Time Limit: 2 Seconds      Memory Limit: 131072 KB


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

K:manacher

 

一個s和t,問你s可以翻轉一次區間,可以變成t,問有多少種翻轉區間個數 

manacherOn求一下,然後首先存在兩種,一個是兩個字符串完全相同的時候,這個時候答案就是s的迴文子串,直接求和就可以

不相同就枚舉兩個串不相同的位置,從頭和尾掃,如果出現了,就往兩邊擴增,看看有多少個串是迴文的,統計一下即可

代碼:

int Find(int x) {   if(x != fa[x]) return fa[x] = Find(fa[x]);  return fa[x];}
char s[maxn + 50];
char s1[maxn + 50];
int dp[maxn * 2 + 100];
char str[maxn * 2 + 100];
int main()
{
    int n,t;
    cin >> t;
    while(t--){
        scanf("%s%s",s + 1,s1 + 1);
        int len = strlen(s + 1);
        for(int i = 0;i <= len * 2 + 10;i++) dp[i] = 0;
        str[0] = '!';
        str[1] = '#';
        int id = 0,mx = 0;
        for(int i = 1; i <= len; i++) {
            str[(i << 1)] = s[i] ;
            str[(i << 1) | 1] = '#';
        }
        int n = (len + 1) << 1;
        str[n] = '\0';
        for(int i = 1; i < n; i++) {
            if(mx > i)
                dp[i] = min(dp[(id << 1) - i],mx - i);
            else
                dp[i] = 1;
            while(str[i + dp[i]] == str[i - dp[i]])
                dp[i]++;
            if(i + dp[i] > mx)
                mx = dp[i] + i,id = i;
        }
        ll cnt = 0;
        for(int i = 1;i <= len;i++)   if(s[i] == s1[i])  cnt++;
        ll ans = 0;
        if(cnt == len){
            for(int i = 1;i < n;i++)   ans += dp[i] / 2;
            printf("%lld\n",ans);
            continue;
        }
        int i,j;
        for(i = 1;i <= len;i++){
            if(s[i] != s1[i]) break;
        }
        for(j = len;j >= 1;j--){
            if(s[j] != s1[j]) break;
        }
        int flag = 0;
        for(int ii = i,jj = j;ii <= j;ii++,jj--){
            if(s1[ii] == s[jj]) continue;
            else{
                flag = 1;
                break;
            }
        }
        if(flag){
            printf("%d\n",0);
            continue;
        }
        cnt = 1;
        for(cnt = 1;i - cnt >= 1 && j + cnt <= len;cnt++){
            if(s1[j + cnt] == s[j + cnt] && s1[i - cnt] == s[i - cnt]
               && s1[j + cnt] == s[i - cnt]) ans++;
            else  break;
        }
        printf("%lld\n",cnt);
    }
    return 0;
}

//8 9 10 11 12

 

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