HDU 5517 【二维树状数组///三维偏序问题】

时间:2022-06-20 21:02:14

题目链接:【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&lpar;二维树状数组&rpar;

    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 &lpar;二维树状数组、cdq分治&rpar;

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

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

    题目链接: 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&plus;二维树状数组

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

  9. BZOJ 3594&colon; &lbrack;Scoi2014&rsqb;方伯伯的玉米田 &lpar;二维树状数组优化DP&rpar;

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

随机推荐

  1. Unity5&period;3官方VR教程重磅登场-系列2

    作者:王寒链接:https://zhuanlan.zhihu.com/p/20485529来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 欢迎继续我们的学习. 北京时间 ...

  2. Android获取文件夹路径 &sol;data&sol;data&sol;

    首先内部存储路径为/data/data/youPackageName/,下面讲解的各路径都是基于你自己的应用的内部存储路径下.所有内部存储中保存的文件在用户卸载应用的时候会被删除. 一. files1 ...

  3. 常用财务软件:用友,金蝶,新中大,速达,管家婆,金算盘,远方,远光,金钥匙,润衡,浪潮,上海博科,易商,任我行,千方百剂,智管,小蜜蜂,SAP,ORACLE,SSA,QAD,MAPICS,JDE。

    常用财务软件:用友,金蝶,新中大,速达,管家婆,金算盘,远方,远光,金钥匙,润衡,浪潮,上海博科,易商,任我行,千方百剂,智管,小蜜蜂,SAP,ORACLE,SSA,QAD,MAPICS,JDE. 申 ...

  4. Python中的上下文管理器和with语句

    Python2.5之后引入了上下文管理器(context manager),算是Python的黑魔法之一,它用于规定某个对象的使用范围.本文是针对于该功能的思考总结. 为什么需要上下文管理器? 首先, ...

  5. Windbg程序调试系列5-高CPU问题分析

    上篇博客中给大家分享了使用Windbg进行Live Debugging: Windbg程序调试系列4-Live Debugging 本篇中我们继续,跟大家分享常见的应用程序高CPU使用率问题分析. 先 ...

  6. BZOJ 5467 Slay the Spire

    BZOJ 5467 Slay the Spire 我的概率基础也太差了.jpg 大概就是这样,因为强化牌至少翻倍,所以打出的牌必定是全部的强化牌或者$k-1$个强化牌,然后剩余的机会打出最大的几个攻击 ...

  7. 11&period;ingress服务

    kubernetes  的service服务我们提到过.service 可以用nodePort的方式和调用公有云LBAAS服务 来对于集群外的client提供服务访问,但是service是工作的osi ...

  8. Python中字符串的截取,列表的截取

    字符串的截取 Python中的字符串用单引号 ' 或双引号 " 括起来,同时使用反斜杠 \ 转义特殊字符. 字符串的截取的语法格式如下: 变量[头下标:尾下标] 索引值以 0 为开始值,-1 ...

  9. 【c&plus;&plus;】删除string中指定的字符

    使用string::iterator(字符串迭代器)从开始 str.begin() 迭代到最后 str.end() ,再使用string.erase(const_iterator p)函数来删除迭代器 ...

  10. haproxy做TCP层的负载均衡

    最新项目中发现,大量游戏玩家访问登录服务器时出现延迟,导致玩家无法登录,愿意可能是登录服务器性能达到极限. 所以目前想通过proxy的方式访问登录服务器集群,避免登录延迟. 1.下载haproxy最新 ...