http://codeforces.com/problemset/problem/12/D
题意
给N (N<=500000)个点,每个点有x,y,z ( 0<= x,y,z <=10^9 )
对于某点(x,y,z),若存在一点(x1,y1,z1)使得x1 > x && y1 > y && z1 > z 则点(x,y,z)是特殊点。
问N个点中,有多少个特殊点。
乍一看以为是裸的三位偏序问题,直接联想到了cdq分治,但是事实上这题和三位偏序有很大的差异,三位偏序问题求的是偏序的组数,但这题问的是完全被小于的个数,cdq分治上很难维护一个点是否已经被“超越”过,也不需要这么麻烦的去维护,事实上一维将x从大到小排序,一维作为树状数组上点的位置,越大的位置在越靠前,一维就是树状数组维护的前缀最大值即可。
#include <map> #include <set> #include <ctime> #include <cmath> #include <queue> #include <stack> #include <vector> #include <string> #include <cstdio> #include <cstdlib> #include <cstring> #include <sstream> #include <iostream> #include <algorithm> #include <functional> using namespace std; #define For(i, x, y) for(int i=x;i<=y;i++) #define _For(i, x, y) for(int i=x;i>=y;i--) #define Mem(f, x) memset(f,x,sizeof(f)) #define Sca(x) scanf("%d", &x) #define Sca2(x,y) scanf("%d%d",&x,&y) #define Scl(x) scanf("%lld",&x); #define Pri(x) printf("%d ", x) #define Prl(x) printf("%lld ",x); #define CLR(u) for(int i=0;i<=N;i++)u[i].clear(); #define LL long long #define ULL unsigned long long #define mp make_pair #define PII pair<int,int> #define PIL pair<int,long long> #define PLL pair<long long,long long> #define pb push_back #define fi first #define se second typedef vector<int> VI; const double eps = 1e-9; const int maxn = 5e5 + 10; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; int N,M,tmp,K,cnt; int Hash[maxn]; struct Node{ int a,b,c; }node[maxn]; bool cmp(Node a,Node b){ return a.a > b.a; } int tree[maxn]; void add(int x,int y){ for(;x <= cnt;x += x & -x) tree[x] = max(tree[x],y); } int getmax(int x){ int s = 0; for(;x > 0;x -= x & -x) s = max(s,tree[x]); return s; } int main() { Sca(N); For(i,1,N) scanf("%d",&node[i].a); For(i,1,N) scanf("%d",&node[i].b); For(i,1,N) scanf("%d",&node[i].c); For(i,1,N) Hash[i] = node[i].c; sort(Hash + 1,Hash + 1 + N); cnt = unique(Hash + 1,Hash + 1 + N) - Hash - 1; For(i,1,N) node[i].c = cnt + 1 - (lower_bound(Hash + 1,Hash + 1 + cnt,node[i].c) - Hash); sort(node + 1,node + 1 + N,cmp); int ans = 0; For(i,1,N){ int j = i; while(j <= N && node[i].a == node[j].a) j++;j--; For(k,i,j){ int t = getmax(node[k].c - 1); if(t > node[k].b) ans++; } For(k,i,j) add(node[k].c,node[k].b); i = j; } Pri(ans); #ifdef VSCode system("pause"); #endif return 0; }