题意:
给出 A集合 (每个元素有两个数字)与 B集合(有三个数字), 如果A集合的最后一个数字 与B集合的最后一个数字相等。就可以造出C集合中的一个元素
a c d 。最后询问C集合中 有多少个元素没有比他大的
思路:
用去重的思想构造出acd这些元素。 之后 a c d这类元素按 a,c,d的顺序从大到小排序,在线段树更新的过程中,因为a元素从大到小,c元素作为边界left,查找是否从c~1000的集合中的最大值比当前的d数字大, 如果有则说明这个acd并不对答案贡献。
#include <iostream>
#include <stdio.h>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 2e5 + 5;
typedef long long ll;
struct p
{
int x,y,z,num;
}a[N], b[N];
int s[N], sum[N];
struct nod{
int maxx;
}tree[N*4];
int cmp(p a,p b )
{
if(a.x!=b.x)return a.x>b.x;
if(a.y!=b.y)return a.y>b.y;
return a.z>b.z;
}
void build(int i,int l,int r)
{
tree[i].maxx=0;
if(l==r)return ;
int mid=(l+r)>>1;
build(i<<1,l,mid);
build(i<<1|1,mid+1,r);
}
void update(int i,int l,int r,int pos,int val)
{
if(l==r&&l==pos)
{
tree[i].maxx=max(tree[i].maxx,val);
return;
}
int mid=(l+r)>>1;
if(pos<=mid) update(i<<1,l,mid,pos,val);
else update(i<<1|1,mid+1,r,pos,val);
tree[i].maxx=max(tree[i<<1].maxx,tree[i<<1|1].maxx);
return ;
}
int query(int i,int l,int r,int left,int right)
{
if(l==left&&r==right)
{
return tree[i].maxx;
}
int mid=(l+r)>>1;
int ans=-1;
if(right<=mid)
{
ans=query(i<<1,l,mid,left,right);
}
else if(left>mid)
{
ans=query(i<<1|1,mid+1,r,left,right);
}
else
{
ans=query(i<<1,l,mid,left,mid);
ans=max(ans,query(i<<1|1,mid+1,r,mid+1,right));
}
return ans;
}
int main()
{
int T;
// freopen("a.txt", "r", stdin);
scanf("%d", &T);
for(int cs=1;cs<=T;cs++)
{
memset(sum,0,sizeof(sum));
memset(s,0,sizeof(s));
memset(b,0,sizeof(b));
memset(a,0,sizeof(a));
int n, m, tot = 0, tot1 = 0;
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++){
int x, y;
scanf("%d%d", &x, &y);
if(s[y] < x){
s[y] = x;
sum[x] = 1;
}else if(s[y] == x) {
sum[x] ++;
}
}
for(int i=1;i<=m;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
if(s[z]) a[++tot].x=s[z], a[tot].y=x,a[tot].z=y,a[tot].num=sum[s[z]];
}
ll ans=0;
sort(a+1,a+1+tot,cmp);
if(tot!=0)
{
b[++tot1]=a[1];
for(int i=2;i<=tot;i++)
{
if(a[i-1].x==a[i].x&&a[i-1].y==a[i].y&&a[i-1].z==a[i].z)
b[tot1].num+=a[i].num;
else b[++tot1]=a[i];
}
build(1,1,1000);
for(int i=1;i<=tot1;i++)
{
int tmp=query(1,1,1000,b[i].y,1000 );
if(tmp<b[i].z) ans+=b[i].num;
update(1,1,1000,b[i].y,b[i].z);
}
}
printf("Case #%d: %lld\n",cs,ans);
}
return 0;
}
/*
10
1 1
5 2
4 1 1
*/