Codeforces961 E. Tufurama(树状数组)

题意:

给定长度为n的序列a
问有多少个数对(x,y),满足:
x<y
a[x]>=y
a[y]>=x

数据范围:n<=2e5

解法:
三个条件:
x<y
a[x]>=y
a[y]>=x

其实前两个可以合并:
x<y<=a[x]
x<=a[y]

即对于每个x,计算[x,a[x]]范围内
满足x<=a[y]的y的数量

每次都暴力插入x<=a[y]的y然后查询显然不可取

观察到x<=a[y],满足左边x减少时x<=a[y]依然成立,因此可以不重置
另开一个结构体存{a[i],i},从大到小排序,枚举x,将满足x<=a[y]的y插入树状数组
每次答案累加[x,a[x]]就能计算出最后的答案

但是a[i]<=1e9,需要离散化,但是将a[x]离散化可能会影响x<=a[x]
其实当a[x]>n的时候,取a[x]=n就可以了

有个坑点是存在x>a[x],不满足x<y<a[x]中的x<a[x]
如果不特判直接用树状数组查询ask(a[x])-ask(x)会出现负数
code:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxm=2e5+5;
struct BIT{
    int c[maxm];
    int lowbit(int i){return i&-i;}
    void add(int i,int t){while(i<maxm)c[i]+=t,i+=lowbit(i);}
    int ask(int i){int ans=0;while(i)ans+=c[i],i-=lowbit(i);return ans;}
}T;
struct Node{
    int v,id;
    bool operator<(Node a){
        return v>a.v;
    }
}e[maxm];
int a[maxm];
int n;
signed main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        if(a[i]>n)a[i]=n;
        e[i]={a[i],i};
    }
    sort(e+1,e+1+n);
    int ans=0;
    int k=1;
    for(int i=n;i>=1;i--){//从大到小枚举x
        while(k<=n&&e[k].v>=i){
            T.add(e[k].id,1);
            k++;
        }
        if(i<=a[i]){//坑点:i>a[i]的情况
            ans+=T.ask(a[i])-T.ask(i);
        }
    }
    cout<<ans<<endl;
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值