zoukankan      html  css  js  c++  java
  • P3531 [POI2012]LIT-Letters(树状数组||逆序对)

    转换成求逆序对的问题。

    如果没有重复的字母,显然是一一对应,用第二个串里对应字符的下标i作为position,然后得到一个position的序列,求这个序列的逆序对个数即为步数。

    因为每交换一次,最多少一组逆序对。

    (这个position代表一种相对前后的关系,我们只需要处理后使序列中没有逆序对即可。)

    当有重复的时候,我们发现,给它一种对应关系即可:第一个a对应第一个a....以此类推。

    注意树状数组中不能出现0,否则lowbit会为0,使其陷入死循环。

    树状数组求逆序对时可以从后往前,然后add进当前值后,查询当前树状数组中严格小于该值的数即可(sum:1~b[i]-1)。(注意下标为数值,存的为个数)

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<vector>
    using namespace std;
    const int N=1000005;
    typedef long long ll;
    int n;
    ll ans;
    string a,b;
    vector<int> v[N];
    int id[N],cnt[N],t[N];
    int read(){
    	int num=0,f=1;
    	char c=getchar();
    	while(c<'0'||c>'9'){
    		if(c=='-') f=-1;
    		c=getchar();
    	}
    	while(c>='0'&&c<='9'){
    		num=num*10+c-'0';
    		c=getchar();
    	}
    	return num*f;
    }
    int lowbit(int x){
    	return x&(-x);
    }
    void add(int x){
    	for(;x<=n;x+=lowbit(x)){
    		t[x]+=1;
    	}
    }
    int ask(int x){
    	int res=0;
    	for(;x;x-=lowbit(x)){
    		res+=t[x];
    	} 
    	return res;
    }
    int main(){
    	//freopen(".in","r",stdin);
    	//freopen(".out","w",stdout);
    	n=read();
    	cin>>a>>b;
    	for(int i=0;i<n;i++){
    		v[b[i]-'A'].push_back(i);
    	}
    	for(int i=0;i<n;i++){
    		id[i+1]=v[a[i]-'A'][cnt[a[i]-'A']]+1;
    		cnt[a[i]-'A']++;
    	}
    	for(int i=n;i>=1;i--){
    		add(id[i]);
    		ans+=ask(id[i]-1);
    	}
    	printf("%lld",ans);	
    	return 0;
    }
    
  • 相关阅读:
    jmeter实现上传文件
    jmeter之调度器设置
    存储过程的几种传参方式
    Charles篡改数据
    软件测试职业发展方向
    最近发现一个有意思的lua游戏引擎,名字叫love2d
    2016,新的一年来到。
    Corona手游教程之widget:Slider篇
    Corona手游教程之widget:PickerWheel篇
    Corona手游教程之widget:ProgressView篇
  • 原文地址:https://www.cnblogs.com/New-ljx/p/15362446.html
Copyright © 2011-2022 走看看