CSAcademy Beta Round #4 Swap Pairing
2016-04-27 13:17
387 查看
题目链接:https://csacademy.com/contest/arhiva/#task/swap_pairing/
大意是给2*n个包含n种数字,每种数字出现恰好2次的数列,每一步操作可以交换相邻的两个数字,问最少需要操作多少次,可以使得所有的同种数字都相邻。
我的做法是考虑不同的数对的数字在原来数列中的位置关系,有三大类,如果我们用[]和{}表示的话就是:
[]{}
[{]}
[{}]
这三种位置情况。
第一种情况对答案的贡献应当是0。
第二种情况对答案的贡献应当是1。
第三种情况对答案的贡献应当是2。
接下来问题就是如何统计。我的方法是先计算所有的pair对,
总共n种数字,那么数对的个数就是(n-1)*n/2。
接下来需要减去第一种情况的个数,再加上第三种情况的个数。
第一种情况的统计应当是比较简单的,第三种情况可以规约到求某个线段内部有多少线段的问题。
统计可以用BIT来维护。
代码如下:
View Code
题解给了另一种做法,可以有一种最优解第一个数字不用移动,则接下来所有数字怎么移动都被固定了,中间仍然是用BIT来维护。
大意是给2*n个包含n种数字,每种数字出现恰好2次的数列,每一步操作可以交换相邻的两个数字,问最少需要操作多少次,可以使得所有的同种数字都相邻。
我的做法是考虑不同的数对的数字在原来数列中的位置关系,有三大类,如果我们用[]和{}表示的话就是:
[]{}
[{]}
[{}]
这三种位置情况。
第一种情况对答案的贡献应当是0。
第二种情况对答案的贡献应当是1。
第三种情况对答案的贡献应当是2。
接下来问题就是如何统计。我的方法是先计算所有的pair对,
总共n种数字,那么数对的个数就是(n-1)*n/2。
接下来需要减去第一种情况的个数,再加上第三种情况的个数。
第一种情况的统计应当是比较简单的,第三种情况可以规约到求某个线段内部有多少线段的问题。
统计可以用BIT来维护。
代码如下:
#include <iostream> #include <vector> #include <algorithm> #include <string> #include <string.h> #include <stdio.h> #include <math.h> #include <queue> #include <stack> #include <map> #include <ctime> #include <set> using namespace std; const int N=123456; int a ; map<int,int> le; map<int,int> ri; pair<int,int> pos ; int v ; int lowbit(int x) { return x & -x; } int get(int x) { int ret=0; while (x) { ret+=v[x]; x-=lowbit(x); } return ret; } void add(int x,int add) { while (x<N) { v[x]+=add; x+=lowbit(x); } } int main () { int n; while (scanf("%d",&n)!=EOF) { memset(v,0, sizeof(v)); le.clear(); ri.clear(); for (int i=1;i<=n;i++) { scanf("%d",a+i); if (le[a[i]]==0) le[a[i]]=i; else ri[a[i]]=i; } int cnt=1; for (map<int,int>::iterator it=le.begin();it!=le.end();it++) { int key=it->first; int val1=it->second; int val2=ri[key]; pos[cnt].first=val1; pos[cnt++].second=val2; } sort(pos+1,pos+cnt); int tot=n/2; long long ret=(tot-1)*1LL*tot/2LL; for (int i=tot;i>=1;i--) { int l=pos[i].first; int r=pos[i].second; ret+=get(r); add(r,1); } memset(v,0,sizeof v); for (int i=1;i<=tot;i++) { int l=pos[i].first; int r=pos[i].second; ret-=get(l); add(r,1); } cout<<ret<<endl; } }
View Code
题解给了另一种做法,可以有一种最优解第一个数字不用移动,则接下来所有数字怎么移动都被固定了,中间仍然是用BIT来维护。
相关文章推荐
- 山东省第五届ACM省赛题——Painting Cottages(求点集的划分)
- CGRectContainsPoint的具体用法解释
- 理解 %IOWAIT (%WIO)
- TIME_WAIT和CLOSE_WAIT状态区别
- You have new mail in /var/spool/mail/root
- leetcode 11. Container With Most Water
- fn contains 包含字符串 三种方法判断
- Troubleshooting 'library cache: mutex X' waits. (文档 ID 1357946.1)
- 习近平主席关心人工智能事业的发展
- WAITEVENT: "library cache: mutex X" (文档 ID 727400.1)
- RAID的介绍和RAID的安装
- HDU 1302 The Snail(模拟题)
- 最新型的TurboMail智慧邮件服务器平台
- 先搜集下关于行动列表和行为树的AI制作
- 10252_Common_permutaion
- 关于服务器raid的一个记录
- 关于服务器raid的一个记录
- LeetCode *** 220. Contains Duplicate III (set::lower_bound)
- 11. Container With Most Water
- int main(int argc,char* argv[])参数简介