Triple HDU - 5517

本文介绍了一种使用线段树数据结构解决特定集合比较问题的方法。通过构造A、B两个集合,并根据一定条件生成C集合,最终统计C集合中不被其他元素覆盖的元素数量。文章详细阐述了实现过程及核心代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:

给出 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
*/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值