题目链接:【http://acm.split.hdu.edu.cn/showproblem.php?pid=5517】

题意:定义multi_set A<a , d>,B<c , d , e>,C<x , y , z>,给出 A , B ,定义 C = A * B = ={⟨a,c,d⟩∣⟨a,b⟩∈A, ⟨c,d,e⟩∈B and b=e} 。求出C之后,求C中一个元素t[i]<a , b , c>是否存在一个元素tmp<x , y , z>使得 x >= a&&y > =b&&z >= c && t != tmp;如果不存在ans++;输出ans即可。

题解:

  首先,我们要剪枝和去重,加入集合A中存在<1 , 3>,<2, 3>,<3, 3> ,<4, 3>,<4, 3>,那么只需要保留<4,3>就可以了,并且记录一下数量。因为前面的数都可以找到比它大的元素。求出C之后,我们依旧要对C去重。那么这道题就是求C某个元素是否存在大于它的元素了。因为这道题中B set里面c,d,很小在生成的C中y,z也很小,都小于1000,那么我们就可以用二维树状数组做了。首先对C进行从大到小排序,树状数组中只记录y,z的值。我们枚举C中的额每一个元素,先查询(1001 - y ,1001 - z),然后在更新(1001 - y ,1001 -  z),应为是从大到小排序的,所以后面的元素的x值一定小于等于前面的元素的x值,s如果查询不为0,那么一定存在某个元素是大于它的。我们一可以直接套CDQ分治的三维偏序模板,为维护值即可。

树状数组:

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 1e5 + 15;
int ic, N, M;
struct Point
{
int x, y, z;
LL w;
Point() {}
Point(int x, int y, int z, LL w): x(x), y(y), z(z), w(w) {}
bool operator < (const Point& T) const
{
if(x != T.x) return T.x < x;
if(y != T.y) return T.y < y;
return T.z < z;
}
bool operator == (const Point T) const
{
return (x == T.x && y == T.y && z == T.z);
}
} P[maxn];
int T[maxn], C[maxn];
int Tbit[1050][1050];
int low_bit(int x)
{
return x & -x;
}
void Bit_add(int x, int y, int val)
{
for(int i = x; i <= 1001; i += low_bit(i))
for(int j = y; j <= 1001; j += low_bit(j))
Tbit[i][j] += val;
}
int Bit_sum(int x, int y)
{
int ret = 0;
for(int i = x; i; i -= low_bit(i))
for(int j = y; j; j -= low_bit(j))
ret += Tbit[i][j];
return ret;
}
int main ()
{
scanf("%d", &ic);
for(int cs = 1; cs <= ic; cs++)
{
scanf("%d %d", &N, &M);
memset(T, 0, sizeof(T));
for(int i = 1; i <= N; i++)
{
int a, b;
scanf("%d %d", &a, &b);
if(a > T[b]) T[b] = a, C[b] = 1;
else if(a == T[b]) C[b]++;
}
int tmp = 0;
for(int i = 1; i <= M; i++)
{
int a, b, c;
scanf("%d %d %d", &a, &b, &c);
if(T[c]) P[++tmp] = Point(T[c], a, b, (LL)C[c]);
}
sort(P + 1, P + 1 + tmp);
N = 1;
for(int i = 2; i <= tmp; i++)
{
if(P[i] == P[N]) P[N].w += P[i].w;
else
P[++N] = P[i];
}
LL ans = 0;
memset(Tbit, 0, sizeof(Tbit));
for(int i = 1; i <= N; i++)
{
if(!Bit_sum(1001 - P[i].y, 1001 - P[i].z)) ans += P[i].w;
Bit_add(1001 - P[i].y, 1001 - P[i].z, 1);
}
printf("Case #%d: %lld\n", cs, ans);
}
return 0;
}

三维偏序:

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 1e5 + 15;
int cs, N, M;
int T[maxn], C[maxn];
LL W[maxn], ans[maxn];
struct Edge
{
int x, y, z, id;
LL w;
Edge() {}
Edge(int x, int y, int z, int id, LL w): x(x), y(y), z(z), id(id), w(w) {}
bool operator < (const Edge & T) const
{
return z < T.z;
}
bool operator == (const Edge & T) const
{
return T.x == x && T.y == y && T.z == z;
}
} B[maxn], p[maxn], t[maxn];
bool cmpx(Edge &a, Edge &b)
{
if(a.x == b.x && a.y == b.y && a.z == b.z)
return a.id < b.id;
else if(a.x == b.x && a.y == b.y)
return a.z < b.z;
else if(a.x == b.x)
return a.y < b.y;
else
return a.x < b.x;
}
bool cmpy(Edge &a, Edge &b)
{
if( a.y == b.y && a.z == b.z)
return a.id < b.id;
else if(a.y == b.y)
return a.z < b.z;
else
return a.y < b.y;
}
//--------------------------------------------------------//树状数组
int c[maxn], maxz = 1001;
inline int lowbit(int x)
{
return x & (-x);
}
void add(int x, int val)
{
while(x <= maxz) c[x] += val, x += lowbit(x);
}
int Get_sum(int x)
{
int ret = 0;
while(x > 0) ret += c[x], x -= lowbit(x);
return ret;
}
//-------------------------------------------------
void cdq(int l, int r)
{
if(l == r) return ;
int mid = (l + r) / 2;
cdq(l, mid), cdq(mid + 1, r);
for(int i = l; i <= r; i++) t[i] = p[i];
sort(t + l, t + mid + 1, cmpy), sort(t + mid + 1, t + r + 1, cmpy);
int a1 = l, a2 = mid + 1;
for(int i = l; i <= r; i++)
{
if(a1 == mid + 1)
ans[t[a2].id] += Get_sum(t[a2].z), a2++;
else if(a2 == r + 1)
add(t[a1].z, 1), a1++;
else if(t[a1].y <= t[a2].y)
add(t[a1].z, 1), a1++;
else
ans[t[a2].id] += Get_sum(t[a2].z), a2++;
}
for(int i = l; i <= mid; i++) add(t[i].z, -1);
}
int main ()
{
scanf("%d", &cs);
for(int ic = 1; ic <= cs; ic++)
{
memset(T, 0, sizeof(T));
memset(ans, 0, sizeof(ans));
scanf("%d %d", &N, &M);
for(int i = 1; i <= N; i++)
{
int a, b;
scanf("%d %d", &a, &b);
if(a > T[b]) T[b] = a, C[b] = 1;
else if(a == T[b]) C[b]++;
}
int tmp = 0;
for(int i = 1; i <= M; i++)
{
int a, b, c;
scanf("%d %d %d", &a, &b, &c);
if(T[c]) ++tmp, p[tmp] = Edge(T[c], a, b, i, (LL)C[c]);
}
sort(p + 1, p + 1 + tmp, cmpx);
N = 1;
for(int i = 2; i <= tmp; i++)
{
if(p[i] == p[N]) p[N].w += p[i].w;
else p[++N] = p[i];
}
if(N <= 1)
{
printf("Case #%d: 0\n", ++ic);
continue;
}
for(int i = 1; i <= N; i++)
{
p[i].x = 100001 - p[i].x;
p[i].y = 1001 - p[i].y;
p[i].z = 1001 - p[i].z;
}
for(int i = 1; i <= N; i++)
{
p[i].id = i;
W[i] = p[i].w;
}
sort(p + 1, p + 1 + N, cmpx);
cdq(1, N);
p[N + 1].x = -1;
for(int i = N; i >= 1; i--)
{
if(p[i].x == p[i + 1].x && p[i].y == p[i + 1].y && p[i].z == p[i + 1].z)
ans[p[i].id] = ans[p[i + 1].id];
}
LL ret = 0;
for(int i = 1; i <= N; i++) if(!ans[i]) ret += W[i];
printf("Case #%d: %lld\n", ic, ret);
}
return 0;
}

  

HDU 5517 【二维树状数组///三维偏序问题】的更多相关文章

  1. hdu 2642 二维树状数组 单点更新区间查询 模板水题

    Stars Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/65536 K (Java/Others) Total Subm ...

  2. hdu 2642二维树状数组 单点更新区间查询 模板题

    二维树状数组 单点更新区间查询 模板 从零开始借鉴http://www.2cto.com/kf/201307/227488.html #include<stdio.h> #include& ...

  3. hdu 5517 Triple(二维树状数组)

    Triple Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Sub ...

  4. HDU 5517---Triple(二维树状数组)

    题目链接 Problem Description Given the finite multi-set A of n pairs of integers, an another finite mult ...

  5. 【 HDU - 4456 】Crowd (二维树状数组、cdq分治)

    BUPT2017 wintertraining(15) #5A HDU 4456 题意 给你一个n行n列的格子,一开始每个格子值都是0.有M个操作,p=1为第一种操作,给格子(x,y)增加z.p=2为 ...

  6. HDU 5465 Clarke and puzzle Nim游戏+二维树状数组

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5465 Clarke and puzzle  Accepts: 42  Submissions: 26 ...

  7. HDU1559 最大子矩阵 (二维树状数组)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1559 最大子矩阵 Time Limit: 30000/10000 MS (Java/Others)  ...

  8. hdu6078 Wavel Sequence dp+二维树状数组

    //#pragma comment(linker, "/STACK:102400000,102400000") /** 题目:hdu6078 Wavel Sequence 链接:h ...

  9. BZOJ 3594: [Scoi2014]方伯伯的玉米田 (二维树状数组优化DP)

    分析 首先每次增加的区间一定是[i,n][i,n][i,n]的形式.因为如果选择[i,j](j<n)[i,j](j<n)[i,j](j<n)肯定不如把后面的全部一起加111更优. 那 ...

随机推荐

  1. redis写定时任务获取root权限

    前提: 1.redis由root用户启动. 2.开启cron的时候,/var/spool/cron linux机器下默认的计划任务,linux会定时去执行里面的任务. 启动服务 :/sbin/serv ...

  2. Spring笔记13--SSH--全注解开发

    SSH全注解开发: (1) 在Action类中添加注解,实现Struts2的注解开发(@NameSpace.@ParentPackage.@Action...) package com.tongji. ...

  3. Linux内核跟踪之trace框架分析【转】

    转自:http://blog.chinaunix.net/uid-20543183-id-1930846.html   ---------------------------------------- ...

  4. C#里partial关键字的作用

    1. 什么是局部类型?C# 2.0 引入了局部类型的概念.局部类型允许我们将一个类.结构或接口分成几个部分,分别实现在几个不同的.cs文件中.局部类型适用于以下情况: (1) 类型特别大,不宜放在一个 ...

  5. Splay算法摘要

    先介绍变量定义 int n; struct Node { //Splay节点定义 ],val,num,siz; //fa:它爸爸:son它儿子,左0右1:val:这个节点的值 //num:这个值的数量 ...

  6. 一、springboot入门

    构建spring boot工程一般采用两种方式 gradle .maven maven方式 pom.xml spring-boot-starter:核心模块,包括自动配置支持.日志和YAML spri ...

  7. 19 Error handling and Go go语言错误处理

    Error handling and Go go语言错误处理 12 July 2011 Introduction If you have written any Go code you have pr ...

  8. opencv(0)安装与配置

    1.windows下 1.1 exe安装 windows下可以安装opencv的exe版本,已经编译好了,很省事. 到https://opencv.org/releases.html下载需要的open ...

  9. hihoCoder #1190 : 连通性·四(点的双连通分量模板)

    时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho从约翰家回到学校时,网络所的老师又找到了小Hi和小Ho. 老师告诉小Hi和小Ho:之前的分组出了点问题,当服 ...

  10. 实时流计算、Spark Streaming、Kafka、Redis、Exactly-once、实时去重

    http://lxw1234.com/archives/2018/02/901.htm