线段树啊最重要的是转化。
可这题连题意都没正确理解,就别提转化了。
有一场gg
set+二分可做, 线段树可做。
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
using namespace std;
#define ms(x) memset(x, 0, sizeof(x))
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
#define ll long long
const int MAXN = 101234;
const int INF = 0x3f3f3f3f;
int MAXy[MAXN<<2], MAXx[MAXN<<2];
void PushUp(int rt) {
MAXx[rt] = max(MAXx[rt<<1], MAXx[rt<<1|1]);
MAXy[rt] = max(MAXy[rt<<1], MAXy[rt<<1|1]);
}
void Build(int l, int r, int rt) {
if(l == r) {
MAXx[rt] = MAXy[rt] = 0;
return;
}
int m = (l + r) >> 1;
Build(lson);
Build(rson);
PushUp(rt);
}
void UpdateV(int op, int p,int key, int l, int r, int rt) {
if(l == r) {
if(op==1)
MAXx[rt] = key;
else
MAXy[rt] = key;
return;
}
int m = (l + r) >> 1;
if(p <= m) UpdateV(op, p, key,lson);
else UpdateV(op, p, key, rson);
PushUp(rt);
}
int QueryMax(int L, int R, int l, int r, int rt, int op) {
if(L<=l && r<=R){
if(op==1) return MAXx[rt];
else return MAXy[rt];
}
int m = (l + r) >> 1;
int ret = -INF;
if(L <= m) ret = max(ret, QueryMax(L, R, lson, op));
if(R > m) ret = max(ret, QueryMax(L, R, rson, op));
return ret;
}
int X[MAXN], Y[MAXN];
int aX[MAXN], aY[MAXN];
int sub[MAXN];
int main(){
int n, o = 0;
scanf("%d", &n);
for(int i=0;i<n;i++){
scanf("%d%d",&X[i],&Y[i]);
aX[i] = X[i], aY[i] = Y[i];
sub[o++] = X[i];
sub[o++] = Y[i];
}
sort(sub, sub+o);
int k = unique(sub, sub+o) - sub;
ms(MAXx), ms(MAXy);
ll ans = 0;
for(int i=n-1;i>=0;i--){ // op==1 find x, else find y
aX[i] = lower_bound(sub, sub+k, aX[i]) - sub;
aY[i] = lower_bound(sub, sub+k, aY[i]) - sub;
// cout<<QueryMax(aY[i], k, 1,k,1, 1)<<" ";
// cout<<QueryMax(aX[i], k, 1,k,1, 2)<<endl;
ans += X[i] - QueryMax(aY[i]+1, k, 1,k,1, 1);
ans += Y[i] - QueryMax(aX[i]+1, k, 1,k,1, 2);
UpdateV(2,aX[i]+1,sub[aY[i]], 1,k,1);
UpdateV(1,aY[i]+1,sub[aX[i]], 1,k,1);
}
printf("%lld\n", ans);
return 0;
}