codeforces540E-树状数组求逆序对

1e9数据范围下的逆序对求解
本文介绍了一种解决数据范围为1e9但存在1e5个区间的问题的方法,通过将未涉及的区间压缩并利用树状数组来高效计算逆序对。

1-1e9的数据范围 但有1e5个区间 所以可以考虑把没有涉及到的区间缩成一个点 然后树状数组求逆序对

 1 #include<bits/stdc++.h>
 2 
 3 #define inf 0x3f3f3f3f
 4 
 5 const int maxn=1000000;
 6 
 7 using namespace std;
 8 
 9 typedef long long ll;
10 
11 int n;
12 
13 ll cnt;
14 
15 ll ans;
16 
17 ll tot;
18 
19 vector<ll> seg;
20 
21 map<ll,int> m;
22 
23 struct node{
24  ll l,r;
25 }s[maxn+10];
26 
27 ll a[maxn+10];
28 
29 ll c[maxn+10];
30 
31 ll t[maxn+10];
32 
33 int lowbit(int x){
34    return x&(-x);
35 }
36 
37 void add(int x,int y){
38     while(x<=cnt){
39         c[x]+=y;
40         x+=lowbit(x);
41     }
42 }
43 
44 ll sum(int x){
45     ll res=0;
46     while(x){
47         res+=c[x];
48         x-=lowbit(x);
49     }
50     return res;
51 }
52 
53 int main()
54 {
55     scanf("%d",&n);
56     for(int i=1;i<=n;i++){
57         scanf("%I64d%I64d",&s[i].l,&s[i].r);
58         seg.push_back(s[i].l);
59         seg.push_back(s[i].r);
60     }
61     unique(seg.begin(),seg.end());
62     sort(seg.begin(),seg.end());
63     for(size_t i=0;i<seg.size();i++){
64            if(i==0){
65                   a[++cnt]=1;
66                   t[cnt]=cnt;
67                   m[seg[i]]=cnt;
68            } else {
69            if(seg[i]-seg[i-1]==1){
70                 a[++cnt]=1;
71                 m[seg[i]]=cnt;
72                 t[cnt]=cnt;
73            } else {
74               a[++cnt]=seg[i]-seg[i-1]-1;
75               t[cnt]=cnt;
76               a[++cnt]=1;
77               m[seg[i]]=cnt;
78               t[cnt]=cnt;
79            }
80            }
81     }
82     for(int i=1;i<=n;i++){
83         int x=m[s[i].l];
84         int y=m[s[i].r];
85         swap(t[x],t[y]);
86     }
87     for(int i=1;i<=cnt;i++){
88         tot+=a[i];
89         add(t[i],a[i]);
90         int temp=sum(t[i])-1;
91         ans+=(tot-temp-1)*a[i];
92     }
93     printf("%I64d\n",ans);
94     return 0;
95 }
View Code

 

转载于:https://www.cnblogs.com/GeniusYang/p/5988274.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值