HDU 6521 Party(线段树+二分+思维贡献)*

这是一篇关于解决HDU 6521 Party问题的博客,主要介绍了如何利用线段树和二分查找优化算法来处理区间效率计算。题目要求在一系列操作中,对每个区间统计未曾聚过的人对数。通过维护每个个体最远认识的边界,并在更新和查询过程中应用二分查找,可以有效地解决这个问题。在实现时需注意数组值的单调性和懒惰标记的更新策略。

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

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6521

题目大意

给定n和m个操作,

n代表序列长度,

每个操作给定一个区间,

代表把这个区间的人聚到一起,

其区间效率是这个区间中多少对人没有在之前的区间中

已经聚过.

题目分析 

线段树+思维转化,

我们可以对每个人,维护一个

数组代表其最远认识到右边的哪一个人,

比如如果区间1,4操作后,那么1最远可以认识到4,

考虑到相互性,我们只需要对每个人维护一端即可.

初始化每个人对应的就是他自己的位置.

更新不难,但查询有点困难,对于区间中数组值

大于右端点的,没有贡献,而在右端点之内的,产生与右端点之差的贡献,

我们无法通过普通的区间求和去表示这一关系.

考虑其数组值的单调性,不难发现我们定义的数组值始终是不减的,

那么我们就可以二分出最大的权重小于右端点的位置点,

有了这个点后就可以进行传统的区间更新了,

我们维护最大值和一个区间和,

注意懒惰标记的更新不是直接赋值而是直接取max,越大越好,

其他一些细节就是数据范围的问题了.

#include<bits/stdc++.h>
using namespace std;

#define debug puts("YES");
#define rep(x,y,z) for(int (x)=(y);(x)<(z);(x)++)
#define ll long long

#define lrt int l,int r,int rt
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define root l,r,rt
#define mst(a,b) memset((a),(b),sizeof(a))
#define pii pair<int,int>
#define fi first
#define se second
#define mk(x,y) make_pair(x,y)
const int mod=1e9+7;
const int maxn=5e5+10;
const int ub=1e6;
const int INF=-1e9;
ll powmod(ll x,ll y){ll t; for(t=1;y;y>>=1,x=x*x%mod) if(y&1) t=t*x%mod; return t;}
ll gcd(ll x,ll y){return y?gcd(y,x%y):x;}
/*
题目大意:
给定n和m个操作,
n代表序列长度,
每个操作给定一个区间,
代表把这个区间的人聚到一起,
其区间效率是这个区间中多少对人没有在之前的区间中
已经聚过.

题目分析:
线段树+思维转化,
我们可以对每个人,维护一个
数组代表其最远认识到右边的哪一个人,
比如如果区间1,4操作后,那么1最远可以认识到4,
考虑到相互性,我们只需要对每个人维护一端即可.
初始化每个人对应的就是他自己的位置.
更新不难,但查询有点困难,对于区间中数组值
大于右端点的,没有贡献,而在右端点之内的,产生与右端点之差的贡献,
我们无法通过普通的区间求和去表示这一关系.
考虑其数组值的单调性,不难发现我们定义的数组值始终是不减的,
那么我们就可以二分出最大的权重小于右端点的位置点,
有了这个点后就可以进行传统的区间更新了,
我们维护最大值和一个区间和,
注意懒惰标记的更新不是直接赋值而是直接取max,越大越好,
其他一些细节就是数据范围的问题了.
*/
int rt[maxn],minv[maxn<<2],x,y;
int maxv[maxn<<2],lazy[maxn<<2];
ll sum[maxn<<2];
void build(lrt){
    lazy[rt]=0;
    if(l==r){
        sum[rt]=maxv[rt]=l;
        return ;
    }
    int mid=l+r>>1;
    build(lson),build(rson);
    maxv[rt]=max(maxv[rt<<1],maxv[rt<<1|1]);
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void pushdown(lrt){
    int mid=l+r>>1;
    if(lazy[rt]){
        lazy[rt<<1]=max(lazy[rt<<1],lazy[rt]);
        lazy[rt<<1|1]=max(lazy[rt<<1|1],lazy[rt]);
        maxv[rt<<1]=max(maxv[rt<<1],lazy[rt]);
        maxv[rt<<1|1]=max(maxv[rt<<1|1],lazy[rt]);
        sum[rt<<1]=1LL*(mid-l+1)*maxv[rt<<1];
        sum[rt<<1|1]=1LL*(r-mid)*maxv[rt<<1|1];
        lazy[rt]=0;
    }
}
int getpos(lrt,int p){
    pushdown(root);
    if(l==r) return maxv[rt];
    int mid=l+r>>1;
    if(p<=mid) return getpos(lson,p);
    else return getpos(rson,p);
}
void update(lrt,int L,int R,int v){
    if(L<=l&&r<=R){
        maxv[rt]=max(maxv[rt],v);
        sum[rt]=1LL*(r-l+1)*maxv[rt];
        lazy[rt]=max(lazy[rt],v);
        return;
    }
    pushdown(l,r,rt);
    int mid=l+r>>1;
    if(L<=mid) update(lson,L,R,v);
    if(mid<R) update(rson,L,R,v);
    maxv[rt]=max(maxv[rt<<1],maxv[rt<<1|1]);
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}

ll getsum(lrt,int L,int R){
    if(L<=l&&r<=R) return sum[rt];
    pushdown(l,r,rt);
    int mid=l+r>>1;
    ll ans=0;
    if(L<=mid) ans+=getsum(lson,L,R);
    if(mid<R) ans+=getsum(rson,L,R);
    maxv[rt]=max(maxv[rt<<1],maxv[rt<<1|1]);
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];
    return ans;
}
int n,m;
int main(){
    while(scanf("%d%d",&n,&m)!=EOF){
        build(1,n,1);
        rep(i,0,m){
            scanf("%d%d",&x,&y);
            int l=1,r=n,p=0;
            while(l<=r){
                int mid=l+r>>1;
                if(getpos(1,n,1,mid)<y){
                    p=mid;l=mid+1;
                }else{
                    r=mid-1;
                }
            }
            p=min(p,y);
            if(x<=p){
                printf("%lld\n",1LL*(p-x+1)*y-getsum(1,n,1,x,p));
                update(1,n,1,x,p,y);
            }else{
                puts("0");
            }
        }
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值