1. 程式人生 > 資訊 >防不勝防:央視曝光 App 彈窗廣告三大陷阱

防不勝防:央視曝光 App 彈窗廣告三大陷阱

[模板] 三維偏序(陌上花開)

Solution:

CDQ分治求解三維偏序。
1、首先三關鍵字排序,保證接下來\(i\)的可行解一定在\([1,i-1]\)中。

2、再對第二關鍵字做歸併排序,保證滿足\(a_j<a_i\)的前提下,實現\(b_j<b_i\)。合併時有兩個區間,\(j<i\)\(j\)\([l,mid]\)中,\(i\)\([mid+1,r]\)中,由於前一次對三關鍵字的排序,使得左區間所有\(a\)小於等於右區間所有\(a\),所以在歸併維護答案時,無需顧忌\(a\)的情況,靠雙指標來保證\(b\)有序,然後同時統計\(c\)的答案即可。

3、歸併時雙指標與樹狀陣列維護第三關鍵字對答案的貢獻,注意重複三維點的情況。

Code:

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define dep(i,a,b) for(int i=(a);i>=(b);--i)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int N=2e5+20;
inline int read() {
    char c=getchar();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0',c=getchar();}
    return x*f;
}
inline void out(int x) {   
	if(x>9) out(x/10);   
	putchar(x%10+'0'); 
}
int n,k;
struct node{
	int a,b,c;
	int cnt;
	int sum;
	void print(){
		cout<<"a="<<a<<" b="<<b<<" c="<<c<<" cnt="<<cnt<<" sum="<<sum<<endl;
	}
	bool operator < (const node &t)const{
		if(t.a!=a)return a<t.a;
		if(t.b!=b)return b<t.b;
		return c<t.c;
	}
	bool operator == (const node &t)const{
		return t.a==a&&t.b==b&&t.c==c;
	}
	node():a(0),b(0),c(0),cnt(0),sum(0){}
	node(int _a,int _b,int _c,int _cnt,int _sum):a(_a),b(_b),c(_c),cnt(_cnt),sum(_sum){}
}q[N],w[N],kep[N];

int ans[N];
#define lowbit(x) (x&(-x))
int c[N];
void add(int pos,int val){
	while(pos<N){
		c[pos]+=val;
		pos+=lowbit(pos);
	}
}
int geta(int pos){
	int ans=0;
	while(pos){
		ans+=c[pos];
		pos-=lowbit(pos);
	}
	return ans;
}

void merge_sort(int l,int r){
	if(l==r)return ;
	int mid = (l+r)>>1;
	merge_sort(l,mid),merge_sort(mid+1,r);
	int i=l,j=mid+1;
	int k=0;
	while(i<=mid&&j<=r){
		if(q[i].b<=q[j].b)add(q[i].c,q[i].cnt),w[k++]=q[i++];
	
		else q[j].sum+=geta(q[j].c),w[k++]=q[j++];
	}
	while(i<=mid)add(q[i].c,q[i].cnt),w[k++]=q[i++];
	while(j<=r)q[j].sum+=geta(q[j].c),w[k++]=q[j++];
	for(int o=l;o<=mid;++o)add(q[o].c,-q[o].cnt);

	for(int i=0,st=l;i<k;++i){
		q[st+i] = w[i];
	}
}

int main(){
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cin>>n>>k;
	rep(i,1,n){
		int x,y,z;
		cin>>x>>y>>z;
		q[i]=node(x,y,z,1,0);
	}
	sort(q+1,q+1+n);
	int siz=0;
	for(int i=1;i<=n;++i){
		int pos = i;
		int cnt = 0;
		while(pos<=n&&q[pos]==q[i]){
			pos++;	
			cnt++;
		}
		kep[++siz] = q[i];
		kep[siz].cnt = cnt;
		i=pos-1;
	}
	for(int i=1;i<=siz;++i){
		q[i] = kep[i];
	}
	merge_sort(1,siz);
	for(int i=1;i<=siz;++i){
		ans[q[i].cnt-1+q[i].sum]+=q[i].cnt;
	}
	for(int i=0;i<n;++i){
		cout<<ans[i]<<"\n";
	}
	return 0;
}