http://codeforces.com/problemset/problem/12/D
線段樹
View Code
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int inf = ~0u>>2;const int N = 500010;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1int Max[N<<2];struct node{ int x,y,z;}in[N];int tot,n;int num[N];int max(int a,int b){ return a>b?a:b;}void pushup(int rt){ Max[rt]=max(Max[rt<<1],Max[rt<<1|1]);}void build(int l,int r,int rt){ Max[rt]=0; if(l==r) return ; int m=(l+r)>>1; build(lson); build(rson);}void update(int p,int val,int l,int r,int rt){ if(l==r){ if(val>Max[rt]) Max[rt]=val; return ; } int m=(l+r)>>1; if(p<=m) update(p,val,lson); else update(p,val,rson); pushup(rt);}int query(int L,int R,int l,int r,int rt){ if(L<=l&&r<=R) return Max[rt]; int m=(l+r)>>1; int ret=0; if(L<=m) ret=max(ret,query(L,R,lson)); if(R>m) ret=max(ret,query(L,R,rson)); return ret;}void init(){ sort(num+1,num+n+1); tot=unique(num+1,num+n+1)-num-1; build(1,tot,1); for(int i=1;i<=n;i++) in[i].x=lower_bound(num+1,num+1+tot,in[i].x)-num;}inline int cmp(node a,node b){ return a.y>b.y;}int main(){ int i,j,k; scanf("%d",&n); for(i=1;i<=n;i++) {scanf("%d",&in[i].x); num[i]=in[i].x;} for(i=1;i<=n;i++) scanf("%d",&in[i].y); for(i=1;i<=n;i++) scanf("%d",&in[i].z); init(); sort(in+1,in+n+1,cmp); int ans=0; for(i=1;i<=n;i=j){ for(j=i;j<=n&&in[j].y==in[i].y;j++){ int z; z=query(in[j].x+1,tot,1,tot,1); if(z>in[j].z) ans++; } for(;i<=j-1;i++) update(in[i].x,in[i].z,1,tot,1); } printf("%d\n",ans); return 0;}/*31 3 52 4 63 5 7*/
樹狀數組
View Code
/*CF 12D樹狀數組好題給你n個整數三元組,對於某個三元組,判斷是否存在一個三元組的元素都大於這個三元組題目給三個數,必然有其道理可以把其中一個數離散化當做樹狀數組的下標,再按照另外某個數排序最後就只需利用樹狀數組數組處理好最後一個數就行了具體做法:比如對x離散化 對y降序排序 x當做樹狀數組的下標每次把y值相同的三元組一起拿出來處理因為前面加進樹狀數組的數的y值肯定比現在這個數的y值要大,這一個數就不必考慮瞭然後就是找前面加進樹狀數組的數中有沒有z座標 大於 當前枚舉的數的z座標,當然是在大於x的區間內這裡與樹狀數組的功能相反了,這裡樹狀數組是求前n項中的最大值,而題目要求下標在x->n間的最大值轉換一下就好了離散化前:1 3 5 7 9離散化後並不是1 2 3 4 5要倒過來:5 4 3 2 1那麼小於x的區間實際上就是大於x的區間*/#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int N = 500010;int c[N];int num[N];int n;struct node{ int x,y,z;}in[N];inline void Max(int &a,int b){ if(a<b) a=b;}void update(int x,int d){ for(;x<N;x+=x&-x) Max(c[x],d);}int sum(int x){ int ans=0; for(;x>0;x-=x&-x) Max(ans,c[x]); return ans;}void init(){ sort(num+1,num+n+1); int tot=unique(num+1,num+n+1)-num-1; for(int i=1;i<=n;i++) in[i].x=tot-(lower_bound(num+1,num+1+tot,in[i].x)-num-1); //把x的相對大小倒了過來 所以小於in[i].x實際表示大於in[i].x;,便於樹狀數組的sum操作}inline int cmp(node a,node b){ return a.y>b.y;}int main(){ int i,j,k; scanf("%d",&n); for(i=1;i<=n;i++) {scanf("%d",&in[i].x); num[i]=in[i].x;} for(i=1;i<=n;i++) scanf("%d",&in[i].y); for(i=1;i<=n;i++) scanf("%d",&in[i].z); init(); memset(c,0,sizeof(c)); sort(in+1,in+n+1,cmp); int ans=0; for(i=1;i<=n;i=j){ for(j=i;j<=n&&in[j].y==in[i].y;j++){ int z=sum(in[j].x-1); if(z>in[j].z) ans++; } for(;i<=j-1;i++) update(in[i].x,in[i].z); } printf("%d\n",ans); return 0;}/*31 3 52 4 63 5 7*/