【题意】Jam喜欢坐标轴上的题,现在给出你一个三维的坐标轴,给出NN个点,坐标分别为(x,y,z)(x,y,z)
如果有两个点(xi, yi, zi)和(xj, yj, zj)若(xi≥xj, yi≥yj,zi≥zj时 这个点的等级就加一,每个等级一开始为0
当然1000001≤x,y,z≤100000 1≤N≤100000
现在求每个点的等级
【分析】首先把每个点按照x升序排序,然后对于y的值建线段树然后每个区间内套上一棵动态添加结点的splay按值排序维护z即可。
【AC CODE】2230ms
#include <bits/stdc++.h> using namespace std; typedef long long LL; #define rep(i,a,n) for(int i = a; i < n; i++) #define repe(i,a,n) for(int i = a; i <= n; i++) #define per(i,n,a) for(int i = n; i >= a; i--) #define clc(a,b) memset(a,b,sizeof(a)) const int INF = 0x3f3f3f3f, MAXN = 100000+10; struct P{ int x,y,z,id; bool operator<(const P&t)const{ return x < t.x; } }p[MAXN]; int ans[MAXN]; struct NODE{ NODE *ch[2], *fa; int sz=0,v; int chd(){//当前儿子是否是左儿子(0-左,1-右) return this == fa->ch[1]; } }; NODE *null = new NODE; NODE* newnode(int v) { NODE *tmp = new NODE(); tmp->sz = 1;tmp->v = v; tmp->ch[0] = tmp->ch[1] = tmp->fa = null; return tmp; } void push_up(NODE *u){//向上更新 u->sz = u->ch[0]->sz+u->ch[1]->sz+1; } void free_all(NODE *u)//释放内存 { if(null == u) return; free_all(u->ch[0]); free_all(u->ch[1]); delete u; } inline void setch(NODE *fa, NODE *u, int p)//重置关联的儿子和父亲,p=0表示u是fa的左儿子1是右儿子 { fa->ch[p] = u, u->fa = fa; } void rot(NODE *u)//旋转 { NODE*y = u->fa; int d = u->chd(); setch(y->fa,u,y->chd()); setch(y,u->ch[d^1],d); setch(u,y,d^1); push_up(y), push_up(u); } NODE* find_kth(NODE *u, int k)//寻找第k小的结点(数列从左往右第k个),u为splay的根 { int d = k - u->ch[0]->sz; if(1 == d) return u;//找到 if(d <= 0) return find_kth(u->ch[0],k);//往左 return find_kth(u->ch[1],k-u->ch[0]->sz-1);//往右 } int find_small(NODE *u, int v) { if(u == null) return 0; if(v < u->v) return find_small(u->ch[0],v); return find_small(u->ch[1],v)+u->ch[0]->sz+1; } void splay(NODE* &rt,int k, NODE *p)//把rt树第k大结点(数列从左往右第k个)伸展到p下面 { NODE *x = find_kth(rt,k); if(x == p) return; while(x->fa != p) { NODE *y = x->fa; if(x->fa->fa != p && x->chd() != y->chd()) rot(y); rot(x); } if(p == null) rt = x; } void insert(NODE *&rt, int k, NODE* x)//把x结点插入第k个后面 { splay(rt,k,null); if(rt->ch[1] == null) setch(rt,x,1); else { NODE *u = rt->ch[1]; while(u->ch[0] != null) u = u->ch[0]; setch(u,x,0); while(x->fa != null) push_up(x), x = x->fa;//向上更新sz } push_up(rt); } void debug(NODE *u) { if(u == null) return; debug(u->ch[0]); printf("%d ", u->v); debug(u->ch[1]); push_up(u); if(u->fa == null) putchar('\n'); } NODE *tz[MAXN<<1]; inline int id(int x, int y){return x+y|x!=y;} void bulid(int x, int y) { tz[id(x,y)] = newnode(-INF); if(x == y) { return; } int m = (x+y)>>1; bulid(x,m); bulid(m+1,y); } void clear(int x, int y) { free_all(tz[id(x,y)]); if(x == y) { return; } int m = (x+y)>>1; clear(x,m); clear(m+1,y); } void update(int x, int y, int qy, int az) { insert(tz[id(x,y)],find_small(tz[id(x,y)],az),newnode(az)); if(x == y) return; int m = (x+y)>>1; if(qy <= m) update(x,m,qy,az); else update(m+1,y,qy,az); } int query(int x, int y, int qx, int qy, int az) { if(qx <= x && y <= qy) { return find_small(tz[id(x,y)],az)-1; } int m = (x+y)>>1,ans = 0; if(qx <= m) ans += query(x,m,qx,qy,az); if(qy > m) ans += query(m+1,y,qx,qy,az); return ans; } int main() { #ifdef SHY freopen("d:\\1.txt", "r", stdin); #endif int t; scanf("%d", &t); while(t--) { int n,mx = 0; scanf("%d", &n); rep(i,0,n) { scanf("%d%d%d", &p[i].x, &p[i].y,&p[i].z); p[i].id = i; mx = max(mx,p[i].y); } sort(p,p+n); bulid(0,mx); int j = 0; rep(i,0,n) { while(j < n && p[j].x <= p[i].x) update(0,mx,p[j].y,p[j].z),j++; ans[p[i].id] = query(0,mx,0,p[i].y,p[i].z)-1; } rep(i,0,n) printf("%d\n", ans[i]); clear(0,mx); } return 0; }