BZOJ3262:陌上花开 & 洛谷3810:三维偏序——题解

两者题一样,方便没有bzoj权限的朋友。

http://www.lydsy.com/JudgeOnline/problem.php?id=3262

https://www.luogu.org/problemnew/show/3810

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

——————————————————————————

CDQ分治不那么裸的题吧……?可能我菜。

首先如果我们做过POJ2532的话, 那这题的思路就不难想:我们对一个维度进行排序,对于另一个维度树状数组统计比它晓得个数有几个,那我们就能够确定它的等级。

不幸的是,这题有三个维度,排掉一个还剩两个,总不能树状数组套树状数组吧(我也不会写啊……)

这时候我们就想到了神奇的CDQ分治(点击此处获得原理),但是这并没有查询和修改操作啊……

好的我们开始对题目重新理解一下!

首先定义我们的修改操作就是往树状数组里添加/删除节点,我们的查询操作就是查询该点的等级。

那么对于一维肯定是要排序的,在那之后我们把根据一维排好的序当做查询/修改的时间,于是我们就神奇的变成了:先询问(该点等级),再修改(将节点插入)的在线问题。

那么CDQ就可以上了!我们对每个区间的节点的二维排序之后套树状数组查三维即可。

PS1:CDQ具体做法:我们每次添加区间前一半的点,后一半进行查询(原因不好用语言表达,大致意思为一个点到区间前端的这段区间可以由若干个CDQ区间的整个前半组成)

PS2:本题还有一个坑点,即相同的点也算是比自己丑(……),而树状数组对于一串相同的点的查询,只有最后一个点的答案正确,其他的点的答案分别为:倒数第二与ans差1,倒数第三与ans差2……所以我们预处理一下即可。

#include<cmath>
#include<cstdio>
#include<queue>
#include<cctype>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=100001;
inline int read(){
    int X=0,w=0; char ch=0;
    while(!isdigit(ch)) {w|=ch==‘-‘;ch=getchar();}
    while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    return w?-X:X;
}
struct flower{
    int x;
    int y;
    int z;
    int num;
    int ans;
}a[N],b[N];
int ans[N],tree[2*N],n,k;
bool cmp(flower a,flower b){
    return (a.x<b.x)||(a.x==b.x&&(a.y<b.y||(a.y==b.y&&a.z<b.z)));
}
bool same(flower a,flower b){
    return (a.x==b.x&&a.y==b.y&&a.z==b.z);
}
inline int lowbit(int t){return t&(-t);}
void add(int x,int y){//将a[x]+y
    for(int i=x;i<=k;i+=lowbit(i))tree[i]+=y;
    return;
}
int query(int x){//1-x区间和
    int res=0;
    for(int i=x;i>0;i-=lowbit(i))res+=tree[i];
    return res;
}
void cdq(int l,int r){
    if(l>=r)return;
    int mid=(l+r)>>1;
    cdq(l,mid);cdq(mid+1,r);
    for(int i=l,j=l,p=mid+1;i<=r;i++){
    if(j<=mid&&(p>r||a[j].y<=a[p].y))b[i]=a[j++];
    else b[i]=a[p++];
    }
    for(int i=l;i<=r;i++){
    a[i]=b[i];
    if(a[i].num<=mid)add(a[i].z,1);
    else a[i].ans+=query(a[i].z);
    }
    for(int i=l;i<=r;i++)if(a[i].num<=mid)add(a[i].z,-1);
    return;
}
int main(){
    n=read();
    k=read();
    for(int i=1;i<=n;i++){
    a[i].x=read();
    a[i].y=read();
    a[i].z=read();
    }
    sort(a+1,a+n+1,cmp);
    flower t;int cnt=1;
    for(int i=n;i>=1;i--){
    if(same(t,a[i])){
        a[i].ans+=cnt;
        cnt++;
    }
    else{
        t=a[i];
        cnt=1;
    }
    }
    for(int i=1;i<=n;i++)a[i].num=i;
    cdq(1,n);
    for(int i=1;i<=n;i++)ans[a[i].ans]++;
    for(int i=0;i<n;i++)printf("%d\n",ans[i]);
    return 0;
}

两者题一样,方便没有bzoj权限的朋友。

时间: 2024-10-07 02:04:08

BZOJ3262:陌上花开 & 洛谷3810:三维偏序——题解的相关文章

【洛谷P3810 三维偏序】

题目描述: 有 n 个元素,第 i 个元素有 ai?,bi,ci? 三个属性,设 f(i,j) 表示满足 aj?≤ai? 且 bj?≤bi? 且 cj?≤ci? 的 j 的数量. 对于 d∈[0,n),求 f(i) = d 的数量. 输入格式: 第一行两个整数n,k分别表示元素数量和最大属性值. 之后 n 行,每行三个整数 ai?.bi?.ci?,分别表示三个属性值. 输出格式: 输出 nn 行,第 d + 1d+1 行表示 f(i) = df(i)=d 的 ii 的数量. 输入样例: 10 3

洛谷P2832 行路难 分析+题解代码【玄学最短路】

洛谷P2832 行路难 分析+题解代码[玄学最短路] 题目背景: 小X来到了山区,领略山林之乐.在他乐以忘忧之时,他突然发现,开学迫在眉睫 题目描述: 山区有n座山.山之间有m条羊肠小道,每条连接两座山,只能单向通过,并会耗费小X一定时间. 小X现在在1号山,他的目的是n号山,因为那里有火车站. 然而小X的体力是有限的.他每通过一条羊肠小道,就会变得更疲劳,导致他通过任意一条羊肠小道的时间都增加1. 输入格式: 第一行两个数,n,m 第2行到第m+1行,每行3个数A,B,C,表示A.B之间有一条

洛谷 P1219 八皇后 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:https://www.luogu.org/problem/show?pid=1219 题目描述 检查一个如下的6 x 6的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行.每列有且只有一个,每条对角线(包括两条主对角线的所有平行线)上至多有一个棋子. 上面的布局可以用序列2 4 6 1 3 5来描述,第i个数字表示在第i行的相应位置有一个棋子,如下: 行号 1 2 3 4 5 6 列号 2 4 6 1 3 5 这只是跳

洛谷 P1311 选择客栈 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:https://www.luogu.org/problem/show?pid=1311 题目描述 丽江河边有n 家很有特色的客栈,客栈按照其位置顺序从 1 到n 编号.每家客栈都按照某一种色调进行装饰(总共 k 种,用整数 0 ~ k-1 表示),且每家客栈都设有一家咖啡店,每家咖啡店均有各自的最低消费. 两位游客一起去丽江旅游,他们喜欢相同的色调,又想尝试两个不同的客栈,因此决定分别住在色调相同的两家客栈中.晚上,

洛谷 P1855 榨取kkksc03 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:https://www.luogu.org/problem/show?pid=1855 题目描述 洛谷的运营组决定,如果一名oier向他的教练推荐洛谷,并能够成功的使用(成功使用的定义是:该团队有20个或以上的成员,上传10道以上的私有题目,布置过一次作业并成功举办过一次公开比赛),那么他可以浪费掉kkksc03的一些时间的同时消耗掉kkksc03的一些金钱以满足自己的一个愿望. Kkksc03的时间和金钱是有限的,

【日常学习】【数学-其他】洛谷1403 约数研究题解

于是又要迎来洛谷那凌然无言以对的题目摘要= = 洛谷1403 约数研究 本题地址:http://www.luogu.org/problem/show?pid=1403 题目描述 科学家们在Samuel星球上的探险得到了丰富的能源储备,这使得空间站中大型计算机"Samuel2"的长时间运算成为了可能.由于在去年一年的辛苦工作取得了不错的成绩,小联允许用"Samuel2"进行数学研究. 小联最近在研究和约数有关的问题,他统计每个正数N的约数的个数,并以f(N)来表示.现

[NOIP2015提高&amp;洛谷P2678]跳石头 题解(二分答案)

[NOIP2015提高&洛谷P2678]跳石头 Description 这项比赛将在一条笔直的河道中进行,河道中分布着一些巨大岩石.组委会已经选择好了两块岩石作为比赛起点和终点.在起点和终点之间,有 N 块岩石(不含起点和终 点的岩石).在比赛过程中,选手们将从起点出发,每一步跳向相邻的岩石,直至到达 终点. 为了提高比赛难度,组委会计划移走一些岩石,使得选手们在比赛过程中的最短跳 跃距离尽可能长.由于预算限制,组委会至多从起点和终点之间移走 M 块岩石(不能 移走起点和终点的岩石). 输入格式

洛谷 P1079 Vigen&#232;re 密码 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:https://www.luogu.org/problem/show?pid=1079 题目描述 16 世纪法国外交家 Blaise de Vigenère 设计了一种多表密码加密算法――Vigenère 密 码.Vigenère 密码的加密解密算法简单易用,且破译难度比较高,曾在美国南北战争中为 南军所广泛使用. 在密码学中,我们称需要加密的信息为明文,用 M 表示:称加密后的信息为密文,用 C 表示:而密钥是一种

洛谷 P2415 集合求和 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:https://www.luogu.org/problem/show?pid=2415 题目描述 给定一个集合s(集合元素数量<=30),求出此集合所有子集元素之和. 输入输出格式 输入格式: 集合中的元素(元素<=1000) 输出格式: 和 输入输出样例 输入样例#1: 2 3 输出样例#1: 10 说明 子集为: [] [2] [3] [2 3] 2+3+2+3=10 保证结果在10^18以内. 分析: 手写容