HDU 5517 Triple (线段树)
来源:互联网 发布:烈焰遮天 源码 双端 编辑:程序博客网 时间:2024/06/05 08:49
题意:
有二元组(a,b),三元组(c,d,e)。当b == e时它们能构成(a,c,d)。
然后,当不存在(u,v,w)!=(a,b,c)且u>=a,v>=b,w>=c时,则是一个better集合里的元素。
问这个better集合有几个元素
思路:
注意到数据范围
对于 N 个二元组(a,b), M 个三元组(c,d,e)
N,M≤1e5
ai,bi≤1e5
ci,di≤1e3 ei≤1e5
假设所有bi和ei都相等
简单的两两组合会组合出1e5*1e5种 (a,c,d)
但考虑到条件:
求出所有(u,v,w)!=(a,b,c)且u>=a,v>=b,w>=c
有对于所有的 (a,b) 若存在 bi==bj 只有ai >= aj
的点对才有可能组成新的better (a,c,d)
即对于一类 bx 或 ex只会存在一个有效的ax
即对于任意一个三元组(c,d,e)只会有一个ax与之组合为新的(a,c,d)
故至多有1e5个可能的better(a,c,d)
那么问题就变成了在1e5(a,c,d)中找better
对于1e5个可能的better(a,c,d)
考虑到条件:
求出所有(u,v,w)!=(a,c,d)且u>=a,v>=c,w>=d
我们可将其按a大在前的顺序排序
对于之后的每个(a,c,d)都可以保证u>=a
那么问题就变成了在1e5(c,d)中找better
考虑到ci,di≤1e3
我们可以利用线段树维护对于每一种ci对应的最大值di
做1e5次区间查询和单点更新
对于每种(ci,di)先查询 [c,max(ci)]是否存在 dj>=di
若存在
则说明所有的(ci,di)(一种(ci,di)可能不止有一个)都是better
查询后再更新ci对应的最大值di即可
代码:
#include <bits/stdc++.h>using namespace std;#define ls l,mid,rt*2#define rs mid+1,r,rt*2+1#define sf l,r,rtconst int MAXN=1e3+100;const int MAXNN=1e5+5;typedef struct Node{ int x,y,z; bool operator < (const Node &a)const{ if(x==a.x) return y==a.y?z>a.z:y>a.y; return x>a.x; }}Node;int tree[4*MAXN],fast[MAXN],st,en,v,ans,fans;int t[MAXNN],cnt[MAXNN];vector <Node> a[MAXNN];map <Node,int> mp;void build(int l,int r,int rt){ tree[rt]=0; if(l==r){fast[l]=rt;return;} int mid=(l+r)/2; build(ls); build(rs);}void update(int rt){ while(rt!=0&&tree[rt]<v){ tree[rt]=v; rt/=2; }}void query(int l,int r,int rt){ if(st>r||en<l||tree[rt]<=ans) return ; if(st<=l&&r<=en) ans=tree[rt]; int mid=(l+r)/2; query(ls); query(rs);}void ini(){ for(int i=1;i<MAXNN-1;i++) t[i]=cnt[i]=0,a[i].clear(); mp.clear(); en=-1; fans=0;}int main(){ int T,n,m,x,y,z; scanf("%d",&T); for(int Case=1;Case<=T;Case++){ ini(); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ scanf("%d%d",&x,&y); if(t[y]<x) t[y]=x,cnt[y]=1; else if(t[y]==x) cnt[y]++; } for(int i=1;i<=m;i++){ scanf("%d%d%d",&x,&y,&z); if(t[z]!=0){ if(!mp[{t[z],x,y}]) a[t[z]].push_back({t[z],x,y}); mp[{t[z],x,y}]+=cnt[z]; en=max(en,x); } } build(1,en,1); int len; for(int i=MAXNN-1;i>0;i--){ len=a[i].size(); if(len){ sort(a[i].begin(),a[i].end()); for(int j=0;j<len;j++){ ans=0;st=a[i][j].y; query(1,en,1); if(ans<a[i][j].z) fans+=mp[a[i][j]]; v=a[i][j].z; update(fast[a[i][j].y]); } } } printf("Case #%d: %d\n",Case,fans); }}
- HDU 5517 Triple (线段树)
- 2015ACM/ICPC亚洲区沈阳站 HDU 5517 Triple (二维线段树)
- HDU 5517 Triple(去重+线段树|二维树状数组)
- Triple HDU
- hdu 5517 Triple(二维树状数组)
- hdu 5517 Triple 二维树状数组
- hdu 3908 Triple
- HDU 3908 Triple
- hdu 3908 Triple
- 【组合】HDU 3908 Triple
- HDU 5517 (ACM 2015 沈阳) Triple [树状数组]
- HDU 3908 Triple (逆向思维)
- triple
- Triple
- HDU 5517 Triple (2015沈阳站I题&&二维树状数组)
- [HDU 5517][2015ACM/ICPC亚洲区沈阳站] Triple 二维树状数组
- HDU 5517 Triple ACM/ICPC 2015 Shenyang(二维树状数组)
- HDU 5517 Triple (枚举+二维树状数组解决三维点数)
- git图形化工具GitKraken的使用——删除文件(rm)
- leveldb学习---0
- 纯虚函数与抽象类
- python decode和encode
- Oracle那些事(9)-启动与关闭
- HDU 5517 Triple (线段树)
- 搜索插入位置
- 【Gradle】eclipse导入Gradle项目
- 机器学习实战-使用朴素贝叶斯分类器来做垃圾邮件分类
- 我的网络编程学习之路——getsockname 和 getpeername 函数
- Codeforces Round #419 (Div. 2)_Karen and Coffee
- windows的grep命令Select-String
- SQL server中设置自增字段
- storm示例之DRPC