[cdq分治] bzoj3262: 陌上花開

bzoj 3262: 陌上花開:http://www.lydsy.com/JudgeOnline/problem.php?id=3262

三維偏序(向我一樣不懂啥偏序的先戳這裏:http://www.cnblogs.com/AKCqhzdy/p/8017372.html
第一個維度直接排序解決
第二個維度的話cdq搞一搞
符合條件就直接丟到樹狀數組裏去
sum=樹狀數組的getsum就ok

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
struct node
{
    int x,tot,s,c,m; //x:沒我好看的數量 tot:屬性跟我完全一樣的個數 
}a[110000];
int c[410000];
node p[110000];
int n,k;
int ans[410000];
bool cmp(node x,node y)
{
    if (x.s!=y.s) return x.s<y.s;
    else if (x.c!=y.c) return x.c<y.c;
    else if (x.m!=y.m) return x.m<y.m;
    else return false;
}
int lowbit(int x)//lowbit第一個不受到管轄的上司/兒子 
{
    return x&-x;
}
void add(int x,int y)
{
    while (x<=k)
    {
        c[x]+=y;
        x+=lowbit(x);   
    }
}
int getsum(int x)
{
    int sum=0;
    while (x>0)
    {
        sum+=c[x];
        x-=lowbit(x);
    }
    return sum;
}
void cdq(int l,int r)
{
    if (l==r) return ;
    int mid=(l+r)/2;
    cdq(l,mid);cdq(mid+1,r);
    int i=l,j=mid+1,len=l;
    while (i<=mid&&j<=r)
    {
        if (a[i].c<=a[j].c)
        {
            add(a[i].m,a[i].tot);
            p[len]=a[i];len++;i++;
        }
        else 
        {
            a[j].x+=getsum(a[j].m);
            p[len]=a[j];len++;j++;
        }
    }
    while (i<=mid)
    {
        add(a[i].m,a[i].tot); p[len]=a[i];len++;i++;
    }
    while (j<=r)
    {
        a[j].x+=getsum(a[j].m); p[len]=a[j];len++;j++;
    }
    for (int i=l;i<=mid;i++) add(a[i].m,-a[i].tot);//據說memset會T
    for (int i=l;i<=r;i++) a[i]=p[i];
}
int main()
{
    scanf("%d%d",&n,&k);
    for (int i=1;i<=n;i++)
    {
        a[i].x=0;
        scanf("%d%d%d",&a[i].s,&a[i].c,&a[i].m);
    }
    sort(a+1,a+1+n,cmp);
    int k=1,head=0;
    for (int i=1;i<=n;i+=k)
    {
        k=1;
        while (a[i].s==a[i+k].s&&a[i].c==a[i+k].c&&a[i].m==a[i+k].m) k++;
        a[++head].tot=k; a[head].s=a[i].s; a[head].c=a[i].c; a[head].m=a[i].m;
    }
    cdq(1,head);
    for (int i=1;i<=head;i++)
    {
        ans[a[i].x+a[i].tot-1]+=a[i].tot;//讓自己儘量的好看就要把和自己一樣的打壓下去
    }
    for (int i=0;i<=n-1;i++) printf("%d\n",ans[i]);
    return 0;
}
發佈了105 篇原創文章 · 獲贊 18 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章