[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;
}
时间: 2024-11-10 07:04:59

[bzoj] 1176 Mokia || CDQ分治的相关文章

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

Description 维护一个W*W的矩阵,初始值均为S.每次操作可以增加某格子的权值,或询问某子矩阵的总权值.修改操作数M<=160000,询问数Q<=10000,W<=2000000. Input 第一行两个整数,S,W;其中S为矩阵初始值;W为矩阵大小 接下来每行为一下三种输入之一(不包含引号): "1 x y a" "2 x1 y1 x2 y2" "3" 输入1:你需要把(x,y)(第x行第y列)的格子权值增加a 输入

BZOJ 1176 Balkan 2007 Mokia CDQ分治

题目大意:有一些操作,给一个坐标代表的点加上一个数,和求出一个矩形中的所有数的和. 思路:一眼题,二位树状数组水过. ... .. . 哪里不对?W<=2000000.逗我?这n^2能开下? 这个时候CDQ神牛又来帮助我们了. 这个题应该算是CDQ分治的模板题了吧,简单分析一下,其实不难. 写这个题之前建议写一下BZOJ 1935 SHOI 2007 Tree 园丁的烦恼 树状数组这个题,是本题的简化版. 按照正常的解法,我们应该建立一个二位的数据结构,然后分别维护两维的信息.如果用动态开点的线

BZOJ 1176 Mokia(cdq分治,解决一类在线查询问题)

题意:维护一个W*W的矩阵,初始值均为S.每次操作可以增加某格子的权值,或询问某子矩阵的总权值.修改操作数M<=160000,询问数Q<=10000,W<=2000000. 这题在bz是贵族题= =,没有链接了 解法:cdq分治,第一维是时间t,第二维是x,第三维是y:每个操作看作一个三维序(t, x, y):假设修改操作是(t, x, y),两个查询操作分别是(t1, x1, y1) 和 (t1, x2, y2):实际上就要问,有多少个修改操作,满足t<=t1,x1<=x&

BZOJ 1176 [Balkan2007]Mokia CDQ分治

题目大意: 维护一个W*W的矩阵,初始值均为S.每次操作可以增加某格子的权值,或询问某子矩阵的总权值.修改操作数M<=160000,询问数Q<=10000,W<=2000000. POJ1195的加强版 没记错的话上午这题还没有中文题目描述的说0.0 好迅速 首先这题看到W就知道二维树状数组挂了 看到M就发现离散化了也搞不了 0.0 这题似乎是CDQ分治被发现之后第二个解决的题目...不过只有会员才知道的世界,今天反应过来刷刷... 修改和询问放在一起分治,一个询问拆分成4个,树状数组处

bzoj 1176 Mokia(CDQ分治)

[题目链接]  http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=96974 [题意] 定义查询操作与修改操作:1 x y z 为将格子(x,y)修改为z:2 x1 y1 x2 y2为查询以(x1,y1)为左上(x2,y2)为右下的子矩阵之和. [思路] cdq分治. 矩阵初始值都为s,所以先不考虑. 首先明确每一个修改操作都互不影响.然后把每一个对子矩阵的询问操作差分为对四个点的“前缀和”操作. 先把所有的操作按照x升序排列

BZOJ 3262: 陌上花开 [CDQ分治 三维偏序]

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行,每

BZOJ 1492 货币兑换 cdq分治或平衡树维护凸包

题意:链接 方法:cdq分治或平衡树维护凸包 解析: 这道题我拒绝写平衡树的题解,我仅仅想说splay不要写挂,insert边界条件不要忘.del点的时候不要脑抽d错.有想写平衡树的去看140142或者留言我. 首先这道题能推出个表达式 f[i]代表第i天最大收益. xx[i]表示将第i天的钱都买A的数量 yy[i]表示将第i天的钱都买B的数量 所以f[i]=max(f[i?1],p[i].a?xx[j]+p[i].b?yy[j])j<i 所以我们要维护这个n^2的递推式 又知道f[i]是由小于

BZOJ 1176 MOKIA

cdq分治. #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxn 2000500 #define maxq 400050 using namespace std; int s,w,type,a,b,c,d,cnt=0,m=0,ans[maxq]; struct ques { int val,opt,x,y,pos,id; }q[maxq]

BZOJ 2141: 排队 CDQ分治+bit

2141: 排队 Description 排排坐,吃果果,生果甜嗦嗦,大家笑呵呵.你一个,我一个,大的分给你,小的留给我,吃完果果唱支歌,大家乐和和.红星幼儿园的小朋友们排起了长长地队伍,准备吃果果.不过因为小朋友们的身高有所区别,排成的队伍高低错乱,极不美观.设第i个小朋友的身高为hi,我们定义一个序列的杂乱程度为:满足ihj的(i,j)数量.幼儿园阿姨每次会选出两个小朋友,交换他们的位置,请你帮忙计算出每次交换后,序列的杂乱程度.为方便幼儿园阿姨统计,在未进行任何交换操作时,你也应该输出该序