bzoj 3262: 陌上花开

Description

有n朵花,每朵花有三个属性:花形(s)、颜色(c)、气味(m),又三个整数表示。现要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量。定义一朵花A比另一朵花B要美丽,当且仅当Sa>=Sb,Ca>=Cb,Ma>=Mb。显然,两朵花可能有同样的属性。需要统计出评出每个等级的花的数量。

Input

第一行为N,K (1 <= N <= 100,000, 1 <= K <= 200,000 ), 分别表示花的数量和最大属性值。
以下N行,每行三个整数si, ci, mi (1 <= si, ci, mi <= K),表示第i朵花的属性

Output

包含N行,分别表示评级为0...N-1的每级花的数量。

Sample Input

10 3
3 3 3
2 3 3
2 3 1
3 1 1
3 1 2
1 3 1
1 1 2
1 2 2
1 3 2
1 2 1

Sample Output

3
1
3
0
1
0
1
0
0
1

HINT

1 <= N <= 100,000, 1 <= K <= 200,000


CDQ分治。先按照x排序。然后我们用归并排序的方法排序y。同时把z放进树状数组

因为x排序好了。所以归并的时候保证左半边的x小于等于右半边。那么我们只需要在放入右半边数的时候记录有几个z比它小就可以了

【果然状态不行各种傻逼错调了好久】

#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
struct number
{
     int x,y,z;
     int p;
     int s;
}a[100001],b[100001],c[100001];
int rank[100001];
int sx[100001];
inline bool cmpx(number x,number y)
{
     if(x.x<y.x)
          return true;
     if(x.x==y.x)
     {
          if(x.y<y.y)
               return true;
          if(x.y==y.y)
               if(x.z<y.z)
                    return true;
     }
     return false;
}
int tr[200001];
int k;
inline int lowbit(int x)
{
     return x&(-x);
}
inline void add(int x,int xx)
{
     int i;
     for(i=x;i<=k;i+=lowbit(i))
          tr[i]+=xx;
}
inline int ask(int x)
{
     int i;
     int ans=0;
     for(i=x;i>=1;i-=lowbit(i))
          ans+=tr[i];
     return ans;
}
inline void solve(int l,int r)
{
	 int mid=(l+r)/2;
	 if(l!=r)
	 {
	      solve(l,mid);
	      solve(mid+1,r);
	      int i1=l,i2=mid+1;
	      int p=0;
	      //memset(tr,0,sizeof(tr));
	      while(i1<=mid&&i2<=r)
	      {
	           if(a[i1].y<=a[i2].y)
	           {
	                p++;
	                c[p]=a[i1];
	                add(c[p].z,c[p].s);
	                i1++;
	           }
	           else
	           {
	                p++;
	                c[p]=a[i2];
	                rank[c[p].p]+=ask(c[p].z);
	                i2++;
	           }
	      }
	      if(i1<=mid)
	      {
	           int i;
               for(i=i1;i<=mid;i++)
               {
                    p++;
                    c[p]=a[i];
                    add(c[p].z,c[p].s);
               }
	      }
	      else if(i2<=r)
	      {
	           int i;
               for(i=i2;i<=r;i++)
               {
                    p++;
                    c[p]=a[i];
                    rank[c[p].p]+=ask(c[p].z);
               }
	      }
	      int i;
	      for(i=l;i<=mid;i++)
	           add(a[i].z,-a[i].s);
	      for(i=l;i<=r;i++)
	           a[i]=c[i-l+1];
	 }
}
int main()
{
//     freopen("test.in","r",stdin);
//     freopen("test.out","w",stdout);
     int n;
     scanf("%d%d",&n,&k);
     int i;
     for(i=1;i<=n;i++)
     {
          scanf("%d%d%d",&b[i].x,&b[i].y,&b[i].z);
          b[i].p=i;
     }
     sort(b+1,b+1+n,cmpx);
     int t=0;
     for(i=1;i<=n;i++)
     {
          if(b[i].x!=b[i-1].x||b[i].y!=b[i-1].y||b[i].z!=b[i-1].z)
          {
               t++;
               a[t]=b[i];
               a[t].s=1;
               a[t].p=t;
          }
          else
               a[t].s++;
     }
     for(i=1;i<=t;i++)
          b[i]=a[i];
     solve(1,t);
     //for(i=1;i<=t;i++)
       //   printf("%d\n",rank[i]);
     for(i=1;i<=t;i++)
          sx[rank[i]+b[i].s]+=b[i].s;
     for(i=1;i<=n;i++)
          printf("%d\n",sx[i]);
     return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值