E - 卿学姐与城堡的墙 树状数组求逆序对、离散化
Source
2016 UESTC Training for Data Structures Problem E
My Solution
树状数组求逆序数
先对uy进行排序,如果a.uy != b.uy 那么uy大的在上面;
如果a.uy == b.uy 那么看vy vy小的在上面, 大的在下面
然后进行1 ~ N的离散化操作,(用树状数组了所以数组不能太大的)
这样就相当于把左边u上的点移到uv内部的,虽然有交点,根据vy大小,有的往上拉,有的往下拉;
然后对对右边vy进行排序,如果a.vy != b.vy 那么uy大的在上面;
如果a.vy == b.vy 那么看uy uy小的在上面, 大的在下面
这样排序相当于把右边v上的交点也移到uv内部去了;
所以已经处理成交点只在uv内部了
然后for i = 1 ~ N
add(seg[i-1].order, 1);
ans += i - get(seg[i-1].order);
扫完就可以输出了☺☺
复杂度 O(nlogn)
另外这里附上一个比较好的讲树状数组求逆序数原理的博客
http://www.cnblogs.com/shenshuyang/archive/2012/07/14/2591859.html
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <queue>
using namespace std;
const int maxn = 200000 + 8;
map<long long,int> s; //用来处理 u == v 的情况
int N; //具体操作的时候要用所以放到全局
struct segment{
long long vy, uy;
int order;
} seg[maxn];
bool cmpu(const segment& a, const segment& b)
{
if(a.uy != b.uy) return a.uy > b.uy;
else return a.vy < b.vy;
}
bool cmpv(const segment& a, const segment& b)
{
if(a.vy != b.vy) return a.vy > b.vy;
else return a.uy < b.uy;
}
//!树状数组求逆序对
int Tree[maxn];
inline int lowbit(int x)
{
return (x&-x);
}
void add(int x, int value)
{
for(int i = x; i <= N; i += lowbit(i))
Tree[i] += value;
}
int get(int x)
{
int sum = 0;
for(int i = x; i; i -= lowbit(i))
sum += Tree[i];
return sum;
}
//!!!!!! u, v, k, b; 会在seg[i].uy = k*u + b; seg[i].vy = k*v + b;这中间过程溢出,所以也要 long long 才行了。
//!!!!!! 这里改了然后过来,WA了10次test1,......test就玩溢出,坑坏我了,前天被坑起啊(┬_┬)
int main()
{
#ifdef LOCAL
freopen("a.txt", "r", stdin);
#endif // LOCAL
long long u, v, k, b;
//!u <= v ...... u == v
long long ans = 0, crosspointsinu = 0;
scanf("%d%lld%lld", &N, &u, &v);
//!....... u == v 的情况处理错了
for(int i = 0; i < N; i++){
scanf("%lld%lld", &k, &b);
seg[i].uy = k*u + b;
seg[i].vy = k*v + b;
s[seg[i].uy]++;
}
//据说可以用set去重
sort(seg, seg + N, cmpu);
for(int i = 0; i < N; i++){
seg[i].order = i+1; //根据u的值进行离散化
}
//
if(u == v){
int times;
for(auto i = s.begin(); i != s.end(); i++){
times = i->second;
if(times != 1){
crosspointsinu += (times*(times-1))/2;
}
}
printf("%lld", crosspointsinu);
}
else{
sort(seg, seg + N, cmpv);
memset(Tree, 0, sizeof Tree);
for(int i = 1; i <= N; i++){
add(seg[i-1].order, 1);
ans += i - get(seg[i-1].order);
}
printf("%lld", ans);
}
return 0;
}
非特殊说明,本博所有文章均为博主原创,未经许可不得转载。
https://www.prolightsfxjh.com/
Thank you!
------from ProLightsfx
非特殊说明,本博所有文章均为博主原创,未经许可不得转载。
如经许可后转载,请注明出处:https://prolightsfxjh.com/article/2016-uestc-training-for-data-structures-e/
共有 0 条评论