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;
    }
    
  • 相关阅读:
    Linnia学习记录
    漫漫考研路
    ENS的学习记录
    KnockoutJS 3.X API 第四章 数据绑定(4) 控制流with绑定
    KnockoutJS 3.X API 第四章 数据绑定(3) 控制流if绑定和ifnot绑定
    KnockoutJS 3.X API 第四章 数据绑定(2) 控制流foreach绑定
    KnockoutJS 3.X API 第四章 数据绑定(1) 文本及样式绑定
    KnockoutJS 3.X API 第三章 计算监控属性(5) 参考手册
    KnockoutJS 3.X API 第三章 计算监控属性(4)Pure computed observables
    KnockoutJS 3.X API 第三章 计算监控属性(3) KO如何实现依赖追踪
  • 原文地址:https://www.cnblogs.com/IltzInstallBI/p/12744225.html
Copyright © 2011-2022 走看看