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

8 篇文章 0 订阅
8 篇文章 0 订阅

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

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值