码迷,mamicode.com
首页 > 其他好文 > 详细

[loj3175]排列鞋子

时间:2020-08-02 12:48:14      阅读:81      评论:0      收藏:0      [点我收藏+]

标签:vector   ||   i++   lld   else   class   update   nbsp   alt   

贪心与最近的鞋子匹配(大小相同且方向相反),记$a_{x}$表示第x双鞋子的左位置,$b_{x}$表示右位置
若$a_{x}>b_{x}$,那么可以交换这两双鞋子并令答案+1,所以不妨设$a_{x}<b_{x}$
对于$x$和$y$,不妨设$a_{x}<a_{y}$,有结论:最终让第$x$双鞋子在第$y$双鞋子左边一定不劣
证明:对剩下的数位置关系(3种)分类讨论,比较两者的逆序对即可
根据分类讨论的讨论,用线段树来维护即可
技术图片
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 100005
 4 #define L (k<<1)
 5 #define R (L+1)
 6 #define mid (l+r>>1)
 7 struct ji{
 8     int a,b;
 9 }a[N];
10 vector<int>va[N],vb[N];
11 int n,x,f[N<<3];
12 long long ans;
13 bool cmp(ji x,ji y){
14     return x.a<y.a;
15 }
16 void update(int k,int l,int r,int x){
17     f[k]++;
18     if (l==r)return;
19     if (x<=mid)update(L,l,mid,x);
20     else update(R,mid+1,r,x);
21 }
22 int query(int k,int l,int r,int x,int y){
23     if((l>y)||(x>r))return 0;
24     if ((x<=l)&&(r<=y))return f[k];
25     return query(L,l,mid,x,y)+query(R,mid+1,r,x,y);
26 }
27 int main(){
28     scanf("%d",&n);
29     for(int i=1;i<=2*n;i++){
30         scanf("%d",&x);
31         if (x>0)vb[x].push_back(i);
32         else va[-x].push_back(i);
33     }
34     x=0;
35     for(int i=1;i<=n;i++)
36         for(int j=0;j<va[i].size();j++){
37             a[++x].a=va[i][j];
38             a[x].b=vb[i][j];
39             if (a[x].a>a[x].b){
40                 ans++;
41                 swap(a[x].a,a[x].b);
42             }
43         }
44     sort(a+1,a+n+1,cmp);
45     for(int i=n;i;i--){
46         ans+=query(1,1,2*n,1,a[i].b-1);
47         update(1,1,2*n,a[i].a);
48         update(1,1,2*n,a[i].b);
49     }
50     printf("%lld",ans);
51 }
View Code

 

[loj3175]排列鞋子

标签:vector   ||   i++   lld   else   class   update   nbsp   alt   

原文地址:https://www.cnblogs.com/PYWBKTDA/p/13418440.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!