bzoj5017: [Snoi2017]炸弹

相信我这题就是(tarjan缩点+拓扑序dp+线段合并+线段树优化建图)

昨天P老大跟我说这题跟C很不一样虚死我了。。看了下路牌发现就是上面那玩意。。。(搞什么啊大佬集体带节奏a)

那么我的水法就是枚举每个炸弹左右延伸咯,学习噶爷瞎搞个随机数列

然后完了。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
const LL mod=1e9+7;
 
struct node
{
    LL x,r;
}a[510000];
LL L[510000],R[510000],minL[510000],maxR[510000];
int n;LL ans;
void extend(LL i)
{
    bool bk=true;
    while(bk==true)
    {
        bk=false;
        while(L[i]>1&&minL[i]<=a[L[i]-1].x)
        {
            bk=true;
            minL[i]=min(minL[i],minL[L[i]-1]), maxR[i]=max(maxR[i],maxR[R[i]-1]);
            L[i]=min(L[i],L[L[i]-1]), R[i]=max(R[i],R[R[i]-1]);
        }
        while(R[i]<n&&maxR[i]>=a[R[i]+1].x)
        {
            bk=true;
            minL[i]=min(minL[i],minL[L[i]+1]), maxR[i]=max(maxR[i],maxR[R[i]+1]);
            L[i]=min(L[i],L[L[i]+1]), R[i]=max(R[i],R[R[i]+1]);
        }
    }
    ans=(ans+ (i*(LL(R[i]-L[i]+1))%mod ) )%mod;
}
int rd[510000];
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%lld%lld",&a[i].x,&a[i].r);
    
    ans=0;
    for(int i=1;i<=n;i++)
        L[i]=R[i]=i,minL[i]=a[i].x-a[i].r,maxR[i]=a[i].x+a[i].r;
    
    for(int i=1;i<=n;i++)rd[i]=i;
    random_shuffle(rd+1,rd+n+1);
    for(int i=1;i<=n;i++)extend( (LL(rd[i])) );
    printf("%lld\n",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/AKCqhzdy/p/8925886.html