[bzoj] 1176 Mokia || CDQ分治

Posted Mrha

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[bzoj] 1176 Mokia || CDQ分治相关的知识,希望对你有一定的参考价值。

原题

给出W×W的矩阵(S没有用,题目有误),给出无限次操作,每次操作的含义为:
输入1:你需要把(x,y)(第x行第y列)的格子权值增加a
输入2:你需要求出以左下角为(x1,y1),右上角为(x2,y2)的矩阵内所有格子的权值和,并输出
输入3:表示输入结束


因为修改之间相互独立,所以可以用CDQ。
三个维度分别为时间,x轴,y轴。
简单的三维偏序即可。

#include<cstdio>
#include<algorithm>
#define N 100010
#define M 200010
using namespace std;
struct hhh
{
    int x,y,z,cnt,sum;
    inline bool operator == (const hhh &b) const
    {
        return x==b.x && y==b.y && z==b.z;
    }
    inline bool operator < (const hhh &b) const
    {
        if (x!=b.x) return x<b.x;
        if (y!=b.y) return y<b.y;
        return z<b.z;
    }
    inline bool operator > (const hhh &b) const
    {
        if (y!=b.y) return y<b.y;
        return z<=b.z;
    }
}t[N],a[N];
int m,head,tail,ans[N],n,s,f[M];

int read()
{
    int ans=0,fu=1;
    char j=getchar();
    for (;j<'0' || j>'9';j=getchar()) if (j=='-') fu=-1;
    for (;j>='0' && j<='9';j=getchar()) ans*=10,ans+=j-'0';
    return ans*fu;
}

void init(int x)
{
    while (x<=s)
    {
    if (f[x]) f[x]=0;
    else break;
    x+=x&-x;
    }
}

int query(int x)
{
    int ans=0;
    while (x)
    {
    ans+=f[x];
    x-=x&-x;
    }
    return ans;
}

void insert(int x,int y)
{
    while (x<=s)
    {
    f[x]+=y;
    x+=x&-x;
    }
}

void CDQ(int l,int r)
{
    if (l==r) return ;
    int mid=(l+r)>>1,idx1=l,idx2=mid+1;
    CDQ(l,mid);
    CDQ(mid+1,r);
    for (int i=l;i<=r;i++)
    {
    if (idx2>r || idx1<=mid && a[idx1]>a[idx2])
    {
        t[i]=a[idx1++];
        insert(t[i].z,t[i].cnt);
    }
    else
    {
        t[i]=a[idx2++];
        t[i].sum+=query(t[i].z);
    }
    }
    for (int i=l;i<=r;i++)
    {
    a[i]=t[i];
    init(a[i].z);
    }
}

int main()
{
    m=read();
    s=read();
    for (int i=1;i<=m;i++)
    {
    t[i].x=read();
    t[i].y=read();
    t[i].z=read();
    }
    sort(t+1,t+m+1);
    head=1;
    n=0;
    while (head<=m)
    {
    tail=head+1;
    while (tail<=m && t[tail]==t[head]) ++tail;
    a[++n]=t[head];
    a[n].cnt=tail-head;
    head=tail;
    }
    CDQ(1,n);
    for (int i=1;i<=n;i++)
    ans[a[i].sum+a[i].cnt-1]+=a[i].cnt;
    for (int i=0;i<m;i++)
    printf("%d\n",ans[i]);
    return 0;
}

以上是关于[bzoj] 1176 Mokia || CDQ分治的主要内容,如果未能解决你的问题,请参考以下文章

bzoj 1176 Mokia(CDQ分治)

[BZOJ1176][Balkan2007]Mokia cdq+树状数组

[bzoj] 1176 Mokia || CDQ分治

BZOJ-1176&2683Mokia&简单题 CDQ分治

cdq分治入门--BZOJ1176: [Balkan2007]Mokia

bzoj 1176 [Balkan2007]Mokia - CDQ分治 - 树状数组