【BZOJ3262】陌上花开(CDQ分治)

【BZOJ3262】陌上花开(CDQ分治)

题解

原来放过这道题目,题面在这里
树套树的做法也请点上面

这回用CDQ分治做的
其实也很简单,
对于第一维排序之后
显然只有前面的对后面的才会产生贡献

那么,使用CDQ分治
先分,每次递归子问题
合并的时候每次考虑前面的对于后面的贡献
最后统计一下答案

如果在清空树状数组的时候用了memset会TLE

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<queue>
#include<vector>
using namespace std;
#define MAX 110000
inline int read()
{
    int x=0,t=1;char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-')t=-1,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    return x*t;
}
int c[MAX<<1],n,K;
int ans[MAX];
struct TNode{int a,b,c,w,ans;}t[MAX];
bool operator<(TNode x,TNode y)
{
    if(x.a!=y.a)return x.a<y.a;
    if(x.b!=y.b)return x.b<y.b;
    return x.c<y.c;
}
bool operator==(TNode a,TNode b)
{
    return a.a==b.a&&a.b==b.b&&a.c==b.c;
}
bool cmp(TNode x,TNode y)
{
    if(x.b!=y.b)return x.b<y.b;
    return x.c<y.c;
}
inline int lowbit(int x){return x&(-x);}
inline void Add(int x,int w){while(x<=K)c[x]+=w,x+=lowbit(x);}
inline int Getsum(int x){int ret=0;while(x)ret+=c[x],x-=lowbit(x);return ret;}
void CDQ(int l,int r)
{
    if(l==r)return;
    int mid=(l+r)>>1;
    CDQ(l,mid);CDQ(mid+1,r);
    sort(&t[l],&t[mid+1],cmp);
    sort(&t[mid+1],&t[r+1],cmp);
    int i=l;
    for(int j=mid+1;j<=r;++j)
    {
        while(i<=mid&&t[j].b>=t[i].b)
        {
            Add(t[i].c,t[i].w);
            ++i;
        }
        t[j].ans+=Getsum(t[j].c);
    }
    for(int j=l;j<i;++j)Add(t[j].c,-t[j].w);
    //memset(c,0,sizeof(c));
}
int main()
{
    n=read();K=read();
    for(int i=1;i<=n;++i)
        t[i].a=read(),t[i].b=read(),t[i].c=read();
    sort(&t[1],&t[n+1]);
    int tot=0;
    for(int i=1;i<=n;++i)
    {
        if(t[i]==t[i-1])++t[tot].w;
        else t[++tot]=t[i],t[tot].w++;
    }
    int N=n;
    n=tot;
    CDQ(1,n);
    for(int i=1;i<=n;++i)ans[t[i].ans+t[i].w-1]+=t[i].w;
    for(int i=0;i<N;++i)
        printf("%d\n",ans[i]);
    return 0;
}
时间: 2024-07-28 16:35:16

【BZOJ3262】陌上花开(CDQ分治)的相关文章

BZOJ3262陌上花开 CDQ分治_BIT+Treap

三个属性, 第一个属性用cdq分治处理, 以第一个属性为关键字从小到大排序, 那么考虑一朵花的等级, 只需考虑排在其前面的花的其他属性(特殊情况是有相同的花,根据题意,对一段相同的花,以排在最后的一朵花的答案为准), 第二三维可以用树状数组加Treap解决, 以每朵花第二属性数值作为位置(因为最大属性k < 2e5, 可以不用离散化, 直接用属性的数值对应树状数组中的下标), 树状数组的每个节点建一颗Treap, 这颗Treap里存的是相应区间里的花的第三个属性, 询问时类似于树状数组求前缀和,

BZOJ3262/洛谷P3810 陌上花开 CDQ分治 三维偏序 树状数组

原文链接http://www.cnblogs.com/zhouzhendong/p/8672131.html 题目传送门 - BZOJ3262 题目传送门 - 落谷P3810 题意 有$n$个元素,第$i$个元素有$a_i$.$b_i$.$c_i$三个属性,设$f(i)$表示满足$a_j\leq a_i$且$b_j\leq b_i$且$c_j\leq c_i$的$j$的数量.对于$d\in [0,n)$,求$f(i)=d$的数量. $n\leq 100000,max\{a_i,b_i,c_i|i

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 3262: 陌上花开 cdq分治 树状数组

https://www.lydsy.com/JudgeOnline/problem.php?id=3262 cdq分治板子题,一维排序,一维分治(cdq里的队列),一维数据结构(树状数组). 学dp优化前来复习--以前好像写过这道题但是没写博客啊--在校oj上写的题都没怎么写博客,追悔莫及 1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #

luogu3810 陌上花开 (cdq分治)

求三维偏序 设三维为a,b,c.先对a排序,这样i的偏序就只能<i. 然而排序的时候需要三个维度都判断一遍,最后还要去重,不然会出现实际应该记答案的数出现在它后面的情况. (排序用的函数里不要写类似于<=之类的东西啊..会出奇奇怪怪的问题的(RE)) 然后分治来做,我们在做区间[l,r]的时候,先去做[l,m]和[m+1,r] 之后左区间[l,m],右区间[m+1,r]都已经按照b排好序了,而且左右两区间内部的答案已经统计过了,所以现在只要考虑左区间中满足(右区间的数)的数量就好了. 那么就也

bzoj 3262: 陌上花开 -- CDQ分治

3262: 陌上花开 Time Limit: 20 Sec  Memory Limit: 256 MB Description 有n朵花,每朵花有三个属性:花形(s).颜色(c).气味(m),又三个整数表示.现要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量.定义一朵花A比另一朵花B要美丽,当且仅当Sa>=Sb,Ca>=Cb,Ma>=Mb.显然,两朵花可能有同样的属性.需要统计出评出每个等级的花的数量. Input 第一行为N,K (1 <= N <= 100,00

洛谷 P3810 【模板】三维偏序(陌上花开) (cdq分治模板)

在solve(L,R)中,需要先分治solve两个子区间,再计算左边区间修改对右边区间询问的贡献. 注意,计算额外的贡献时,两子区间各自内部的顺序变得不再重要(不管怎么样左边区间的都发生在右边之前),于是就少了一维 https://www.lydsy.com/JudgeOnline/problem.php?id=3262 https://www.luogu.org/problemnew/show/P3810 此题每个操作既是修改又是查询 对于此题,先按一维排序,在solve(L,R)中先solv

P3810 【模板】三维偏序(陌上花开)(cdq分治)

思路 看到这种偏序类的题目,而且不要求强制在线,可以立刻想到cdq分治 注意这题有一个问题,就是询问的是小于等于而不是小于,如果相等的话两个元素会相互贡献,而cdq的特点是右区间不能对左边有影响,所以要先去重,再然后就是板子 代码 #include <cstdio> #include <cstring> #include <algorithm> using namespace std; int n,maxn; namespace BIT{ int bit[200100]

P3810 【模板】三维偏序(陌上花开)cdq分治

传送门:https://www.luogu.org/problemnew/show/P3810 cdq分治的模板题,第一层外部排序,第二层cdq归并排序,这个时候不用考虑第一次的顺序,第三次用树状数组. 注意,不要用memset,用队列保存加上的值,最后在把加上的值减去就行了. #include <algorithm> #include <iterator> #include <iostream> #include <cstring> #include &l