题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5517
题意:
有一个二元组A<a,b>,三元组B<c,d,e>。
现在需要你用这俩集合重新组成一个三元组C<a,c,d>,a来源于A,c,d来源于B,当且仅当b==e时,C才能由A和B组成。
现在需要你求出有多少个<a,c,d>满足:不存在属于C的一个三元组<u,v,w>使得,u>=a,v>=c,w>=d。
解题思路:
(这题一开始没能理解题目说啥。。。汗)
这就是相当于让你找<a,c,d>单项里最大的三元组有几个呗,那么我们可以将这些三元组进行按a排,按c排,按d排,降序的方式存下,
然后使用二维树状数组的方式,找到符合要求的二元组。
代码:
#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <string.h>
#include <queue>
using namespace std;
const int maxn=1e5+50;
int c[1005][1005];
int a1[maxn],cnt[maxn];
struct Tree{
int a,c,d;
int num;
}tree[maxn];
int cmp(const Tree a,const Tree b)
{
if(a.a!=b.a)return a.a<b.a;
if(a.c!=b.c)return a.c<b.c;
return a.d<b.d;
}
int lowbit(int x)
{
return x&(-x);
}
int judge(int x)
{
int sum=0;
int i=tree[x].c;
while(i<1005)
{
int j=tree[x].d;
while(j<1005)
{
sum+=c[i][j];
j+=lowbit(j);
}
i+=lowbit(i);
}
return sum;
}
void update(int x)
{
int i=tree[x].c;
while(i>0)
{
int j=tree[x].d;
while(j>0)
{
c[i][j]++;
j-=lowbit(j);
}
i-=lowbit(i);
}
}
int main()
{
int t;
int n,m;
int a,b,c1,d,e;
scanf("%d",&t);
int cas=0;
while(t--)
{
memset(a1,-1,sizeof(a1));
memset(cnt,0,sizeof(cnt));
memset(c,0,sizeof(c));
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&a,&b);
if(a1[b]<a)
{
a1[b]=a;
cnt[b]=1;
}
else if(a1[b]==a)
cnt[b]++;
}
int no=0;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&c1,&d,&e);
if(a1[e]==-1)continue;
tree[no].a=a1[e];
tree[no].c=c1;
tree[no].d=d;
tree[no].num=cnt[e];
no++;
}
sort(tree,tree+no,cmp);
int k=0;
for(int i=1;i<no;i++) /*去重*/
{
if(tree[k].a==tree[i].a&&tree[k].c==tree[i].c&&tree[k].d==tree[i].d)
{
tree[k].num+=tree[i].num;
}
else
{
k++;
tree[k].a=tree[i].a;
tree[k].c=tree[i].c;
tree[k].d=tree[i].d;
tree[k].num=tree[i].num;
}
}
long long ans=0;
for(int i=k;i>=0;i--)
{
if(judge(i)==0)ans+=(long long )tree[i].num;
update(i);
}
printf("Case #%d: %lld\n",++cas,ans);
}
}