您的位置:首页 > 其它

HDU 5517 (ACM 2015 沈阳) Triple [树状数组]

2015-11-02 21:07 393 查看
题意:给你N个二元组,M个三元组,在二元组与三元组的最后一个数相同时,两者去掉最后一个数,用剩下的三个数拼凑出一个新的三元组<X,Y,Z>,求这些三维坐标的上凸面的点数。

范围:N,M<=10W,拼凑出来的三元组的X,Y,Z的X<=10W,Y,Z<=1000

解法:很容易发现Y,Z的坐标很小,即变成了求按X排序后,求Y,Z右上方是否还有点,如果没有点了,说明这个点是上凸的点。这个过程可以用二维树状数组完成。当然之前有一个贪心过程,就是对应最后一个数相同的时候,X要取前面二元组中最大的,且需要记录一下取最大值的二元组的数量,最后一旦发现点上凸,加上这个记录的数量即可。

代码:

注意代码中的<X,Y,Z>对应着题目意思的<Y,Z,X>,为了少写一个重载orz

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<iostream>
#include<stdlib.h>
#include<set>
#include<map>
#include<queue>
#include<vector>
#include<bitset>
#pragma comment(linker, "/STACK:1024000000,1024000000")
template <class T>
bool scanff(T &ret){ //Faster Input
char c; int sgn; T bit=0.1;
if(c=getchar(),c==EOF) return 0;
while(c!='-'&&c!='.'&&(c<'0'||c>'9')) c=getchar();
sgn=(c=='-')?-1:1;
ret=(c=='-')?0:(c-'0');
while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');
if(c==' '||c=='\n'){ ret*=sgn; return 1; }
while(c=getchar(),c>='0'&&c<='9') ret+=(c-'0')*bit,bit/=10;
ret*=sgn;
return 1;
}
#define inf 1073741823
#define llinf 4611686018427387903LL
#define PI acos(-1.0)
#define lth (th<<1)
#define rth (th<<1|1)
#define rep(i,a,b) for(int i=int(a);i<=int(b);i++)
#define drep(i,a,b) for(int i=int(a);i>=int(b);i--)
#define gson(i,root) for(int i=ptx[root];~i;i=ed[i].next)
#define tdata int testnum;scanff(testnum);for(int cas=1;cas<=testnum;cas++)
#define mem(x,val) memset(x,val,sizeof(x))
#define mkp(a,b) make_pair(a,b)
#define findx(x) lower_bound(b+1,b+1+bn,x)-b
#define pb(x) push_back(x)
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define lowbit(x) (x&(-x))
#define NN 100100
struct node{
int x,y,z,cot;
bool operator < (const node temp)const{
return z<temp.z;
}
}a[NN],b[NN];
int n,m;
int la[NN],ra[NN],lb[NN],rb[NN];
int c[1010][1010];

void add(int i,int j){
for(int x=i;x<=1000;x+=lowbit(x))
for(int y=j;y<=1000;y+=lowbit(y)){
c[x][y]++;
}
}
int getsum(int i,int j){
int sum=0;
for(int x=i;x>0;x-=lowbit(x))
for(int y=j;y>0;y-=lowbit(y)){
sum+=c[x][y];
}
return sum;
}

map<pii,int> mp;
int main(){
tdata{
scanff(n);scanff(m);
rep(i,1,n){
scanff(a[i].y);
scanff(a[i].z);
}
rep(i,1,m){
scanff(b[i].x);
scanff(b[i].y);
scanff(b[i].z);
b[i].x=1001-b[i].x;
b[i].y=1001-b[i].y;
}
sort(a+1,a+1+n);
sort(b+1,b+1+m);
mem(la,0);mem(ra,0);mem(lb,0);mem(rb,0);mem(c,0);
rep(i,1,n){
if(i==1||a[i].z!=a[i-1].z)la[a[i].z]=i;
if(i==n||a[i].z!=a[i+1].z)ra[a[i].z]=i;
}
rep(i,1,m){
if(i==1||b[i].z!=b[i-1].z)lb[b[i].z]=i;
if(i==m||b[i].z!=b[i+1].z)rb[b[i].z]=i;
}
rep(i,1,100000){
if(lb[i]==0)continue;
if(la[i]==0){
rep(j,lb[i],rb[i]){
b[j].z=0;
b[j].cot=0;
}
continue;
}
int maxx=-inf,cot=0;
rep(j,la[i],ra[i]){
if(a[j].y==maxx)cot++;
else if(a[j].y>maxx){
cot=1;
maxx=a[j].y;
}
}
rep(j,lb[i],rb[i]){
b[j].z=maxx;
b[j].cot=cot;
}
}
sort(b+1,b+1+m);
ll ans=0;
drep(i,m,1){
if(i==1||b[i].z!=b[i-1].z){
mp.clear();
rep(j,i,m){
mp[mkp(b[j].x,b[j].y)]++;
add(b[j].x,b[j].y);
if(j==m||b[j].z!=b[j+1].z)break;
}
rep(j,i,m){
if(getsum(b[j].x,b[j].y)-mp[mkp(b[j].x,b[j].y)]==0){
ans+=ll(b[j].cot);
}
if(j==m||b[j].z!=b[j+1].z)break;
}
}
}
printf("Case #%d: %lld\n",cas,ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: