http://poj.openjudge.cn/practice/1028/
百练上的题目,好怀念。
我最开始都是在百练刷的中文题哦~~~有快100题了吧,(*^__^*) 嘻嘻……,水题一堆堆,所以对这个OJ感情蛮深的。。
现在改成好多小组类型的了。。。
这个是线段树呀,开始没想通。FCJ同学提示了下,说类似矩形,说可以按从小到大排序后,就可以相当与矩形查找了。
后来想通了。
很神的方法。记得做逆序数的时候,就是这种方法,动态地插入,保证后面的不影响前面的。这个一样的。按其中一维排序后,然后插入,以y 为线段树区间,z为值,查x比当前x校(这个需要预处理)在区间[0,y)内的最小值是否比z小。有小的话,说明不是special了。然后再插入。
细节注意,因为相同大小的不能算,所以,x相同的元素需要都查询完再统一插入。
vim越来越顺手啦~~~嘿嘿~~~
#include <set> #include <map> #include <queue> #include <stack> #include <math.h> #include <stdio.h> #include <stdlib.h> #include <iostream> #include <limits.h> #include <string.h> #include <string> #include <algorithm> #define MID(x,y) ( ( x + y ) >> 1 ) #define L(x) ( x << 1 ) #define R(x) ( x << 1 | 1 ) #define FOR(i,s,t) for(int i=(s); i<(t); i++) #define BUG puts("here!!!") #define STOP system("pause") #define file_r(x) freopen(x, "r", stdin) #define file_w(x) freopen(x, "w", stdout) using namespace std; const int MAX_LEN = 110; const int MAX = 100010; const int inf = 200; struct NODE { int x, y, z; void get() { scanf("%d%d%d", &x, &y, &z); } }; NODE team[MAX]; bool cmp(NODE a,NODE b) { return a.x < b.x; } struct Tnode{ // 一维线段树 int l,r,min; int len() { return r - l;} int mid() { return MID(l,r);} bool in(int ll,int rr) { return l >= ll && r <= rr; } void lr(int ll,int rr){ l = ll; r = rr;} }; Tnode node[MAX_LEN<<2]; void Build(int t,int l,int r) { node[t].lr(l,r); node[t].min = inf; if( node[t].len() == 1 ) return ; int mid = MID(l,r); Build(L(t),l,mid); Build(R(t),mid,r); } void Updata(int t,int l,int r,int val) { if( node[t].in(l,r) ) { node[t].min = min(node[t].min, val); return ; } if( node[t].len() == 1 ) return ; int mid = node[t].mid(); if( l < mid ) Updata(L(t),l,r,val); if( r > mid ) Updata(R(t),l,r,val); node[t].min = min(node[t].min, min(node[L(t)].min, node[R(t)].min)); } int Query(int t,int l,int r) { if( node[t].in(l,r) ) return node[t].min; if( node[t].len() == 1 ) return inf; int mid = node[t].mid(); int ans = inf; if( l < mid ) ans = min(ans, Query(L(t),l,r)); if( r > mid ) ans = min(ans, Query(R(t),l,r)); return ans; } int pre[MAX]; int solve(int n) { sort(team, team+n, cmp); int st = 0; pre[0] = st; FOR(i, 1, n) { pre[i] = st; while( team[i].x == team[i-1].x && i < n ) { pre[i] = st; i++; } st = i; pre[i] = st; } Build(1, 0, 102); int sum = 0; FOR(i, 0, n) { if( pre[i] == 0 ) continue; FOR(k, pre[i-1], i) Updata(1, team[k].y, team[k].y+1, team[k].z); do { sum += ( Query(1, 0, team[i].y) < team[i].z ? 1 : 0 ); i++; }while( pre[i] == pre[i-1] && i < n); i--; } return n - sum; } int main() { int n; while( ~scanf("%d", &n) ) { FOR(i, 0, n) team[i].get(); int ans = solve( n ); printf("%d\n", ans); } return 0; }