zoukankan      html  css  js  c++  java
  • codeforces 1256F Equalizing Two Strings 题解

    Codeforces Round #598 (Div. 3) F

    首先无论反转多长的子串 最后的效果能够等同于进行若干次相邻两个字母交换
    把相邻交换看作后者前移

    abcd->abdc->adbc->dabc
    dabc->dacb->dcab
    dcab->dcab
    dcba
    

    接下来分类讨论

    • 如果有字母在S和T中出现次数不同

    显然 (sf{NO}) 这还需要解释吗

    • 如果S和T中存在一个字母出现不止一次

    把 S 中这两个字母想办法变成相邻 这一定能做到
    然后每次操作交换 S 的这两个相邻字母 T就可以任意交换
    S 不变 T 一定可以变成 S

    因为可以看作每一个字符任意右移 每次把需要移动的移过去就行了

    • 其它情况

    我们可以先想办法把 S 变成升序 同时对T任意选择两个相邻字母每次交换这两个 这一步的次数取决于 S 中逆序对的个数 假设这个数为(x)
    这样之后再把 T 变成升序 假设 T 中逆序对个数为(y) 这一步需要的步数等于(y+1)(y-1)((x)为奇数) 或 (y)((x)为偶数)

    如果(x)为奇数 在"任意选择两个相邻字母每次交换这两个"操作中 S排序完后T的逆序对显然会增加或减少一个 而如果(x)为偶数 这个数不会改变

    同时也要在S上进行这些操作(任意选择两个相邻字母每次交换这两个)

    可以看出(x+y)为偶数是能做到上面一步 否则如果一个为升序 另一个逆序对必会为1

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    typedef long long LL;
    
    LL T,n;
    string s,t;
    LL cnt[2][28] = {0};
    
    LL tr[35] = {0};
    LL lowbit(LL x){ return (x & (-x)); }
    void modify(LL x){ for(;x <= 26;x += lowbit(x)) tr[x] ++; }
    LL query(LL x){ LL ret = 0; for(;x;x -= lowbit(x)) ret += tr[x]; return ret; }
    // 树状数组求逆序对
    // 好像没必要啊
    
    int main(){
    	cin >> T;
    	while(T --){
    		memset(cnt,0,sizeof(cnt));
    		cin >> n; cin >> s >> t;
    		for(LL i = 0;i < n;i ++){
    			cnt[0][s[i] - 'a' + 1] ++;
    			cnt[1][t[i] - 'a' + 1] ++;
    		}
    		
    		LL dif = 0; for(LL i = 1;i <= 26;i ++) if(cnt[0][i] != cnt[1][i]) dif = 1;
    		if(dif){ cout << "NO" << endl; continue; }
    		    // 情况1
          LL sam = 0; for(LL i = 1;i <= 26;i ++) if(cnt[0][i] >= 2) sam = 1;
    		if(sam){ cout << "YES" << endl; continue; }
            // 情况2
    		
    		LL ans = 0,ant = 0;
    		memset(tr,0,sizeof(tr));
    		for(LL i = 0;i < n;i ++){ ans += query(s[i] - 'a' + 1); modify(s[i] - 'a' + 1); }
    		memset(tr,0,sizeof(tr));
    		for(LL i = 0;i < n;i ++){ ant += query(t[i] - 'a' + 1); modify(t[i] - 'a' + 1); }
    		
    		cout << ((ans & 1) == (ant & 1) ? "YES" : "NO") << endl;
    	}
    	return 0;
    }
    
  • 相关阅读:
    netty解决TCP的拆包和粘包的解决办法
    HTML图片热区map area的用法
    JWT应用
    React-router4简约教程
    axios中文文档
    如何区分Babel中的stage-0,stage-1,stage-2以及stage-3(一)
    python datetime offset-aware与offset-navie相互转换
    DJango跨域中间键
    Javacript实现倒计时
    CAN协议,系统结构和帧结构
  • 原文地址:https://www.cnblogs.com/IltzInstallBI/p/12744225.html
Copyright © 2011-2022 走看看