• Educational Codeforces Round 96 (Rated for Div. 2) E. String Reversal 题解(思维+逆序对)


    题目链接

    题目大意

    给你一个长度为n的字符串,可以交换相邻两个元素,使得这个字符串翻转,求最少多少种次数改变

    题目思路

    如果要求数组排序所需要的冒泡次数,那其实就是逆序对

    这个也差不多,但是如果是相同字符,用的应该是对应的最近的这个字母。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=2e5+5;
    int n,cnt[30],ans[maxn],tree[maxn<<2];
    char s[maxn];
    vector<int> pos[30];
    int query(int node,int L,int R,int l,int r){
    	if(L<=l&&r<=R){
    		return tree[node];
    	}
    	int mid=(l+r)>>1,sum=0;
    	if(mid>=L) sum+=query(node<<1,L,R,l,mid);
    	if(mid<R) sum+=query(node<<1|1,L,R,mid+1,r);
    	return sum; 
    }
    void update(int node,int l,int r,int pos){
    	if(l==r){
    		tree[node]++;
    		return ;
    	}
    	int mid=(l+r)>>1;
    	if(mid>=pos) update(node<<1,l,mid,pos);
    	else update(node<<1|1,mid+1,r,pos);
    	tree[node]=tree[node<<1]+tree[node<<1|1];
    }
    int main(){
    	scanf("%d %s",&n,s+1);
    	for(int i=1;i<=n;i++){
    		int x=s[i]-'a'+1;
    		pos[x].push_back(n-i+1);
    	}
    	for(int i=n;i>=1;i--){
    		int x=s[i]-'a'+1;
    		ans[i]=pos[x][cnt[x]++];
    	}
    	ll pr=0;
    	for(int i=1;i<=n;i++){
    		int bug=query(1,1,ans[i],1,n);
    		pr+=query(1,ans[i],n,1,n);
    		update(1,1,n,ans[i]);
    	}
    	printf("%lld
    ",pr);
    	return 0;
    } 
    
    卷也卷不过,躺又躺不平
  • 相关阅读:
    C#细说多线程(下)
    C#细说多线程(上)
    C#:进程、线程、应用程序域(AppDomain)与上下文分析
    C#委托与事件
    SQL Server 查询优化器运行方式
    SQL优化之索引分析
    C#反射机制
    Sql注入
    JAVA内存泄漏解决办法
    spring4声明式事务—02 xml配置方式
  • 原文地址:https://www.cnblogs.com/hunxuewangzi/p/13822263.html
Copyright © 2020-2023  润新知