陌上花开 HYSBZ - 3262 (CDQ分治)
陌上花开
有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
Hint
思路:
CDQ分治解决三维偏序的模板题。
推荐去这里学习:https://oi-wiki.org/misc/cdq-divide/
我写了两个版本,分别是第二维sort和归并排序。
代码(sort版本):
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define ALL(x) (x).begin(), (x).end()
#define sz(a) int(a.size())
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define gg(x) getInt(&x)
#define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
#define du3(a,b,c) scanf("%d %d %d",&(a),&(b),&(c))
#define du2(a,b) scanf("%d %d",&(a),&(b))
#define du1(a) scanf("%d",&(a));
using namespace std;
typedef long long ll;
ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
ll powmod(ll a, ll b, ll MOD) {a %= MOD; if (a == 0ll) {return 0ll;} ll ans = 1; while (b) {if (b & 1) {ans = ans * a % MOD;} a = a * a % MOD; b >>= 1;} return ans;}
void Pv(const vector<int> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%d", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("\n");}}}
void Pvl(const vector<ll> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%lld", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("\n");}}}
inline void getInt(int *p);
const int maxn = 1000010;
const int inf = 0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/
struct node {
    int x, y, z;
    int cnt;
    int ans;
} a[maxn];
node b[maxn];
int Ans[maxn];
bool cmpx(node aa, node bb)
{
    if (aa.x != bb.x) {
        return aa.x < bb.x;
    } else if (aa.y != bb.y) {
        return aa.y < bb.y;
    } else {
        return aa.z < bb.z;
    }
}
bool cmpy(node aa, node bb)
{
    if (aa.y != bb.y) {
        return aa.y < bb.y;
    } else {
        return aa.z < bb.z;
    }
}
int n, k;
int tree[maxn];
int lowbit(int x)
{
    return -x & x;
}
void add(int x, int v)
{
    while (x < maxn) {
        tree[x] += v;
        x += lowbit(x);
    }
}
int ask(int x)
{
    int res = 0;
    while (x) {
        res += tree[x];
        x -= lowbit(x);
    }
    return res;
}
void CDQ(int l, int r)
{
    if (l == r) {
        return ;
    }
    int mid = (l + r) >> 1;
    CDQ(l, mid);
    CDQ(mid + 1, r);
    // 排序第二维度
    sort(b + l, b + mid + 1, cmpy);
    sort(b + mid + 1, b + r + 1, cmpy);
    int pl = l;
    int pr = mid + 1;
    while (pr <= r) {
        while (pl <= mid && b[pl].y <= b[pr].y) {
            add(b[pl].z, b[pl].cnt);// 第三维度加入到树桩数组中
            pl++;
        }
        b[pr].ans += ask(b[pr].z);// 树桩数组求前缀和的形式来求也满足第三维的偏序个数
        pr++;
    }
    repd(i, l, pl - 1) {
        add(b[i].z, -b[i].cnt);//  清空树桩数组。
    }
}
int main()
{
    //freopen("D:\\code\\text\\input.txt","r",stdin);
    //freopen("D:\\code\\text\\output.txt","w",stdout);
    du2(n, k);
    repd(i, 1, n) {
        du3(a[i].x, a[i].y, a[i].z);
    }
    int m = 0;
    int cnt = 0;
    sort(a + 1, a + 1 + n, cmpx);// 排序第一维度
    repd(i, 1, n) {
        cnt++;
        // 把三个维度都相同的缩在一起
        if (a[i].x != a[i + 1].x || a[i].y != a[i + 1].y || a[i].z != a[i + 1].z) {
            b[++m] = a[i];
            b[m].cnt = cnt;
            cnt = 0;
        }
    }
    CDQ(1, m);
    repd(i, 1, m) {
        Ans[b[i].ans + b[i].cnt - 1] += b[i].cnt;
    }
    repd(i, 0, n - 1) {
        printf("%d\n", Ans[i] );
    }
    return 0;
}
inline void getInt(int *p)
{
    char ch;
    do {
        ch = getchar();
    } while (ch == ' ' || ch == '\n');
    if (ch == '-') {
        *p = -(getchar() - '0');
        while ((ch = getchar()) >= '0' && ch <= '9') {
            *p = *p * 10 - ch + '0';
        }
    } else {
        *p = ch - '0';
        while ((ch = getchar()) >= '0' && ch <= '9') {
            *p = *p * 10 + ch - '0';
        }
    }
}
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define ALL(x) (x).begin(), (x).end()
#define sz(a) int(a.size())
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define gg(x) getInt(&x)
#define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
#define du3(a,b,c) scanf("%d %d %d",&(a),&(b),&(c))
#define du2(a,b) scanf("%d %d",&(a),&(b))
#define du1(a) scanf("%d",&(a));
using namespace std;
typedef long long ll;
ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
ll powmod(ll a, ll b, ll MOD) {a %= MOD; if (a == 0ll) {return 0ll;} ll ans = 1; while (b) {if (b & 1) {ans = ans * a % MOD;} a = a * a % MOD; b >>= 1;} return ans;}
void Pv(const vector<int> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%d", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("\n");}}}
void Pvl(const vector<ll> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%lld", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("\n");}}}
inline void getInt(int *p);
const int maxn = 1000010;
const int inf = 0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/
struct node {
    int x, y, z;
    int cnt;
    int ans;
} a[maxn];
node b[maxn];
node c[maxn];
int Ans[maxn];
bool cmpx(node aa, node bb)
{
    if (aa.x != bb.x) {
        return aa.x < bb.x;
    } else if (aa.y != bb.y) {
        return aa.y < bb.y;
    } else {
        return aa.z < bb.z;
    }
}
bool cmpy(node aa, node bb)
{
    if (aa.y != bb.y) {
        return aa.y < bb.y;
    } else {
        return aa.z < bb.z;
    }
}
int n, k;
int tree[maxn];
int lowbit(int x)
{
    return -x & x;
}
void add(int x, int v)
{
    while (x < maxn) {
        tree[x] += v;
        x += lowbit(x);
    }
}
int ask(int x)
{
    int res = 0;
    while (x) {
        res += tree[x];
        x -= lowbit(x);
    }
    return res;
}
void CDQ(int l, int r)
{
    if (l == r) {
        return ;
    }
    int mid = (l + r) >> 1;
    CDQ(l, mid);
    CDQ(mid + 1, r);
    int ql = l;
    int qr = mid + 1;
    repd(i, l, r) {
        if (qr > r || (ql <= mid && b[ql].y <= b[qr].y)) {
            add(b[ql].z, b[ql].cnt);
            c[i] = b[ql++];
        } else {
            b[qr].ans += ask(b[qr].z);
            c[i] = b[qr++];
        }
    }
    ql = l;
    qr = mid + 1;
    repd(i, l, r) {
        if (qr > r || (ql <= mid && b[ql].y <= b[qr].y)) {
            add(b[ql].z, -b[ql].cnt);
            ql++;
        } else {
            qr++;
        }
    }
    repd(i, l, r) {
        b[i] = c[i];
    }
}
int main()
{
    //freopen("D:\\code\\text\\input.txt","r",stdin);
    //freopen("D:\\code\\text\\output.txt","w",stdout);
    du2(n, k);
    repd(i, 1, n) {
        du3(a[i].x, a[i].y, a[i].z);
    }
    int m = 0;
    int cnt = 0;
    sort(a + 1, a + 1 + n, cmpx);// 排序第一维度
    repd(i, 1, n) {
        cnt++;
        // 把三个维度都相同的缩在一起
        if (a[i].x != a[i + 1].x || a[i].y != a[i + 1].y || a[i].z != a[i + 1].z) {
            b[++m] = a[i];
            b[m].cnt = cnt;
            cnt = 0;
        }
    }
    CDQ(1, m);
    repd(i, 1, m) {
        Ans[b[i].ans + b[i].cnt - 1] += b[i].cnt;
    }
    repd(i, 0, n - 1) {
        printf("%d\n", Ans[i] );
    }
    return 0;
}
inline void getInt(int *p)
{
    char ch;
    do {
        ch = getchar();
    } while (ch == ' ' || ch == '\n');
    if (ch == '-') {
        *p = -(getchar() - '0');
        while ((ch = getchar()) >= '0' && ch <= '9') {
            *p = *p * 10 - ch + '0';
        }
    } else {
        *p = ch - '0';
        while ((ch = getchar()) >= '0' && ch <= '9') {
            *p = *p * 10 + ch - '0';
        }
    }
}
												
											陌上花开 HYSBZ - 3262 (CDQ分治)的更多相关文章
- Luogu 3810 & BZOJ 3262 陌上花开/三维偏序 | CDQ分治
		
Luogu 3810 & BZOJ 3263 陌上花开/三维偏序 | CDQ分治 题面 \(n\)个元素,每个元素有三个值:\(a_i\), \(b_i\) 和 \(c_i\).定义一个元素的 ...
 - BZOJ3262 陌上花开 —— 三维偏序 CDQ分治
		
题目链接:https://vjudge.net/problem/HYSBZ-3262 3262: 陌上花开 Time Limit: 20 Sec Memory Limit: 256 MBSubmit ...
 - bzoj3262: 陌上花开  三维偏序cdq分治
		
三维偏序裸题,cdq分治时,左侧的x一定比右侧x小,然后分别按y排序,对于左侧元素按y大小把z依次插入到树状数组里,其中维护每个左侧元素对右侧元素的贡献,在bit查询即可 /************* ...
 - P3810 【模板】三维偏序(陌上花开)(cdq分治)
		
思路 看到这种偏序类的题目,而且不要求强制在线,可以立刻想到cdq分治 注意这题有一个问题,就是询问的是小于等于而不是小于,如果相等的话两个元素会相互贡献,而cdq的特点是右区间不能对左边有影响,所以 ...
 - BZOJ 3262 cdq分治 OR 树套树
		
注意判断 三个条件都一样的-- (CDQ分治 其实并不是很难理解 只是想不到--) CDQ分治: //By SiriusRen #include <cstdio> #include < ...
 - Luogu P3810 【模板】三维偏序(陌上花开)(CDQ分治)
		
题目 以三维偏序为例来讲一下CDQ分治. CDQ的本质就是把一个序列分成两段,计算左边对右边的贡献,然后分治. 不过一般都是先分治到底再从下往上算,这样可以先归并再算. 比如这道题,我们先按第一维排序 ...
 - Day6 - K - 陌上花开 HYSBZ - 3262
		
有n朵花,每朵花有三个属性:花形(s).颜色(c).气味(m),用三个整数表示. 现在要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量. 定义一朵花A比另一朵花B要美丽,当且仅Sa>= ...
 - 【BZOJ 3262】 3262: 陌上花开 (CDQ分治)
		
3262: 陌上花开 Description 有n朵花,每朵花有三个属性:花形(s).颜色(c).气味(m),又三个整数表示.现要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量.定义一朵花A ...
 - bzoj 3262 陌上花开 - CDQ分治 - 树状数组
		
Description 有n朵花,每朵花有三个属性:花形(s).颜色(c).气味(m),又三个整数表示.现要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量.定义一朵花A比另一朵花B要美丽,当 ...
 
随机推荐
- C#常用处理数据类型转换、数据源转换、数制转换、编码转换相关的扩展
			
public static class ConvertExtensions { #region 数据类型转换扩展方法 /// <summary> /// object 转换成string ...
 - HDU 1688 Sightseeing 【输出最短路+次短路条数】
			
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1688 题目大意:给n个点,m条有向边.再给出起点s, 终点t.求出s到t的最短路条数+次短路条数. 思 ...
 - ESXi 制作模板并优化 Centos
			
1.修改网络配置 vi /etc/sysconfig/network-scripts/ifcfg-eth0 #编辑network配置文件修改以下两项 (eth1同理) ONBOOT=yes BOOTP ...
 - [Agc036C]Triangle_数学
			
Triangle 题目链接:https://atcoder.jp/contests/agc036/tasks/agc036_a 题解: 我开始的时候以为是$Millar-Rabin$加$Pollard ...
 - shell中防止意外发生的两个实用的设置
			
set -o nounset set -o errexit set -o nounset 在默认情况下,遇到不存在的变量,会忽略并继续执行,而这往往不符合预期,加入该选项,可以避免恶果扩大,终止脚本的 ...
 - oracle导出空表
			
1.先查询数据库空表 select 'alter table '||table_name||' allocate extent;' from user_tables where num_rows=0 ...
 - Spring5的总体架构图
			
Spring5的主体架构图 主要是四大部分:Web.Data Access/Integration.Core Container.中间层,具体见下图:
 - SQLite基础-4.数据定义语言(DDL)
			
目录 一.创建数据库 1. 创建方式 2. 数据库命名规范 二. 创建表 1. 基本用法 2. 数据表命名规范 3. 字段命名规范 三. 删除表 一.创建数据库 1. 创建方式 在第二章中我们讲了如何 ...
 - PAT B1015A1062德才论(25)
			
题目描述 宋代史学家司马光在<资治通鉴>中有一段著名的"德才论":"是故才德全尽谓之圣人,才德兼亡谓之愚人,德胜才谓之君子,才胜德谓之小人.凡取人之术,苟不得 ...
 - iview给布局MenuItem标签绑定点击事件
			
@click.native="menuHandleClick"