题目:
有 n 个元素,第 i 个元素有 ai 、bi 、ci 三个属性,设 f(i) 表示满足 aj ≤ ai 且 bj ≤ bi 且 cj ≤ ci 的 j 的数量。对于 d∈[0,n),求 f(i)=d 的 i 的数量。
题解:
可以对第一维a进行排序(O(nlogn)),然后对第二维进行归并排序(O(nlogn)),在归并时对于 bi <= bj可以将对应的 ci 的个数加进树状数组(O(nlogk)),在bi > bj 时统计小于cj的数量,最后回溯的时候不要忘了清空树状数组。对于重复的数,可以先进行去重,详见代码。
p3810AC代码:
1 #include <bits/stdc++.h> 2 #define numm ch-48 3 #define pn putchar(' ') 4 #define pd putchar(' ') 5 #define debug(args...) cout<<#args<<"->"<<args<<endl 6 //#define bug cout<<"*******************"<<endl 7 using namespace std; 8 template<typename T> 9 void read(T &res) { 10 char ch;bool flag=false; 11 while(!isdigit(ch=getchar()))(ch=='-')&&(flag=true); 12 for(res=numm;isdigit(ch=getchar());res=(res<<1)+(res<<3)+numm); 13 flag&&(res=-res); 14 } 15 template<typename T> 16 void write(T x) { 17 if(x<0) x=-x,putchar('-'); 18 if(x>9) write(x/10); 19 putchar(x%10+48); 20 } 21 typedef long long ll; 22 const int maxn=100000+10; 23 const int inf=0x3f3f3f3f; 24 struct node { 25 int a,b,c; ///a,b,c三个变量 26 int ans,cnt; 27 bool operator<(const node &x) const{ 28 if(a!=x.a) return a<x.a; 29 else if(b!=x.b) return b<x.b; 30 else if(c!=x.c) return c<x.c; 31 } 32 }e[maxn],temp[maxn];///temp[]:存放归并后的数 33 int tree[maxn<<1],k,res[maxn]; ///tree[]:树状数组 34 int lowbits(int x) { 35 return x&-x; 36 } 37 void add(int i,int v) { 38 while(i<=k) { 39 tree[i]+=v; 40 i+=lowbits(i); 41 } 42 } 43 int query(int i) { 44 int ans=0; 45 while(i) { 46 ans+=tree[i]; 47 i-=lowbits(i); 48 } 49 return ans; 50 } 51 void cdq(int l,int r) { 52 if(l==r) { 53 e[l].ans+=e[l].cnt-1; ///不要把自己算进去,-1 54 return ; 55 } 56 int mid=l+r>>1; 57 cdq(l,mid); 58 cdq(mid+1,r); 59 int i=l,j=mid+1,op=l;///双指针进行归并 60 while(j<=r) { ///把右边大于左边的都统计一次 61 while(i<=mid&&e[i].b<=e[j].b) { 62 add(e[i].c,e[i].cnt); ///把个数加到对应的权值之上 63 temp[op++]=e[i]; 64 i++; 65 } 66 e[j].ans+=query(e[j].c); 67 temp[op++]=e[j]; 68 j++; 69 } 70 for(int j=l;j<i;j++) ///清空树状数组 71 add(e[j].c,-e[j].cnt); 72 while(i<=mid) ///左边(i那部分)有可能没算完 73 temp[op++]=e[i],i++; 74 75 for(i=l;i<=r;i++)///把排序后的temp赋值给e 76 e[i]=temp[i]; 77 } 78 int main() 79 { 80 int n; 81 read(n);read(k);///k:a,b,c的大小上限 82 for(int i=1;i<=n;i++) 83 read(e[i].a),read(e[i].b),read(e[i].c); 84 sort(e+1,e+1+n); 85 int cnt=1,tot=0; 86 for(int i=2;i<=n;i++) { ///去重 87 if(e[i-1].a^e[i].a||e[i-1].b^e[i].b||e[i-1].c^e[i].c) { 88 e[++tot]=e[i-1]; 89 e[tot].cnt=cnt; 90 e[tot].ans=0; 91 cnt=1; 92 } 93 else cnt++; 94 } 95 e[++tot]=e[n]; 96 e[tot].cnt=cnt; 97 e[tot].ans=0; 98 cdq(1,tot); 99 for(int i=1;i<=tot;i++) 100 res[e[i].ans]+=e[i].cnt;///最后的答案为ans的数有多少个,所以加上cnt 101 for(int i=0;i<n;i++) 102 write(res[i]),pn; 103 return 0; 104 }