90分线段树,WA了最后一个点,求助
查看原帖
90分线段树,WA了最后一个点,求助
479625
sy_ming楼主2021/7/19 10:28
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int MAXN=3e5+5;
long long ans=0;
int n,m;
struct data
{
    int num,val;
    bool operator<(const data &b) const //运算符重载用于sort
    {
        return val<b.val;
    }
}a[MAXN];
struct ask //询问
{
    int l,r,i;
    bool operator<(const ask &b) const
    {
        return r<b.r;
    }
}asks[MAXN];
struct good_pair
{
    int l,r;
    bool operator<(const good_pair &b) const
    {
        return r<b.r;
    }
}pairss[MAXN];
int cnt=0;
struct node
{
    int l,r,w_a,w_b;
}tree[MAXN*4];
void build(int l,int r,int k)
{
    tree[k].l=l,tree[k].r=r;
    if(l==r)
    {
        tree[k].w_a=0;
        return;
    }
    int mid=(l+r)/2;
    build(l,mid,k*2);
    build(mid+1,r,k*2+1);
    tree[k].w_a=0;
}
void update_a(int p,int k) //加入左端点,p为端点位置
{
    if(tree[k].r<p||tree[k].l>p) return;
    if(tree[k].l==p&&tree[k].r==p)
    {
        
        tree[k].w_a++;
        return;
    }
    int mid=(tree[k].l+tree[k].r)/2;
    if(p<=mid) update_a(p,k*2);
    else update_a(p,k*2+1);
    tree[k].w_a=tree[k*2].w_a+tree[k*2+1].w_a;
}
void update_b(int p,int k)//加入右端点
{
    if(tree[k].r<p||tree[k].l>p) return;
    if(tree[k].l==p&&tree[k].r==p)
    {
        
        tree[k].w_b++;
        return;
    }
    int mid=(tree[k].l+tree[k].r)/2;
    if(p<=mid) update_b(p,k*2);
    else update_b(p,k*2+1);
    tree[k].w_b=tree[k*2].w_b+tree[k*2+1].w_b;
}
int query_a(int a,int b,int k)//查询[a,b]区间内左端点的数量
{
    if(tree[k].r<a||tree[k].l>b) return 0;
    if(tree[k].l>=a&&tree[k].r<=b)
        return tree[k].w_a;
    else
        return query_a(a,b,k*2)+query_a(a,b,k*2+1);
}
int query_b(int a,int b,int k)//查询[a,b]区间内右端点的数量
{
    if(tree[k].r<a||tree[k].l>b) return 0;
    if(tree[k].l>=a&&tree[k].r<=b)
        return tree[k].w_b;
    else
        return query_b(a,b,k*2)+query_b(a,b,k*2+1);
}
int main()
{
    scanf("%d%d",&n,&m);
    for (int i = 1; i <= n; i++)
    {
        int temp;
        scanf("%d",&temp);
        a[i].num=i;
        a[i].val=temp;
    }
    sort(a+1,a+n+1);
    build(1,n,1);
    //找出好对
    pairss[++cnt].l=min(a[1].num,a[2].num);
    pairss[cnt].r=max(a[1].num,a[2].num);
    pairss[++cnt].l=min(a[n].num,a[n-1].num);
    pairss[cnt].r=max(a[n].num,a[n-1].num);
    for (int i = 2; i <= n-1; i++)
    {
        if(a[i].val-a[i-1].val==a[i+1].val-a[i].val)
        {
            pairss[++cnt].l=min(a[i].num,a[i-1].num);
            pairss[cnt].r=max(a[i].num,a[i-1].num);
            pairss[++cnt].l=min(a[i].num,a[i+1].num);
            pairss[cnt].r=max(a[i].num,a[i+1].num);
        }
        else if(a[i].val-a[i-1].val>a[i+1].val-a[i].val)
        {      
            pairss[++cnt].l=min(a[i].num,a[i+1].num);
            pairss[cnt].r=max(a[i].num,a[i+1].num);
        }
        else
        {
            pairss[++cnt].l=min(a[i].num,a[i-1].num);
            pairss[cnt].r=max(a[i].num,a[i-1].num);
        }
    }
    sort(pairss+1,pairss+cnt+1);
    //记录询问
    for (int i = 1; i <= m; i++)
    {
        int l,r;
        scanf("%d%d",&l,&r);
        asks[i].i=i,asks[i].l=l,asks[i].r=r;
    }
    sort(asks+1,asks+m+1);
    int ccnt=1;
    for (int i = 1; i <= m; i++)
    {
        while (pairss[ccnt].r<=asks[i].r&&ccnt<=cnt)
        {
            update_a(pairss[ccnt].l,1);
            update_b(pairss[ccnt].r,1);
            ccnt++;
        }
        ans+=1ll*(query_b(1,asks[i].r,1)-query_a(1,asks[i].l-1,1))*asks[i].i;
    }
    printf("%lld\n",ans);
    return 0;    
}
2021/7/19 10:28
加载中...