Tufurama

直接按题意模拟计数即可,拿个单调栈和树状数组维护下...
题目不是求二元组的数量吗?i<j&&ai>=j&&aj>=i.
这是一个二维问题对吧,我们一维一维的解决.首先对于ai>n的直接取n就好,因为n一定是满足条件的.
然后我们令val和id,字面意思呐.我们都排序一下,对于原数组按val升序排序.当然在排序之前,我们需要存下它的值对吧,因为我们后面要枚举的.
后面枚举的话也是一个一个处理的,我们考虑枚举i=1到n.然后对于每个i判断下ai这个位子合法的数量,我们很容易知道,假如aj<i当前,那么这个j就不可能作为贡献,且以后也不会成为贡献.这个j就可以在树状数组中删除.然后对于其他的,直接query(a[i])即可.
代码如下:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=2e5+5;
struct vv{
    ll id,val;
}a[N];
bool cmp(vv x,vv y)
{
    return x.val<y.val;
}
ll n,ca[N],sum[N],vis[N];
ll lowbit(ll x) { return x&(-x); }
void add(ll pos,ll val)
{
    while(pos<=n)
    {
        sum[pos]+=val;
        pos+=lowbit(pos);
    }
}

ll query(ll pos)
{
    ll res=0;
    while(pos)
    {
        res+=sum[pos];
        pos-=lowbit(pos);
    }return res;
}

int main()
{
    scanf("%lld",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i].val);
        a[i].id=i;
        ca[i]=min(a[i].val,n);
        add(i,1);
    }
    sort(a+1,a+1+n,cmp);
    ll ans=0;
    for(int i=1,num=1;i<=n;i++)
    {
        if(!vis[i]) {add(i,-1);vis[i]=1;};//假如这个数没有被淘汰.就淘汰它.
        while(num<=n&&i>a[num].val)
        {
            if(!vis[a[num].id]) add(a[num].id,-1),vis[a[num].id]=1;
            num++;
        }
        ans+=query(ca[i]);
    }
    printf("%lld\n",ans);
    return 0;
}
lpt的小屋 文章被收录于专栏

我想要一份甜甜的爱情

全部评论

相关推荐

不愿透露姓名的神秘牛友
07-24 18:34
点赞 评论 收藏
分享
不愿透露姓名的神秘牛友
07-15 22:48
牛马人的牛马人生:建议就是把北邮几个字放大就行了。北邮本硕按理来说完全不用担心啊
点赞 评论 收藏
分享
白火同学:先说结论,准大三不是特别好找实习,boss沟通300+没有实习是很正常的情况。一是暑期实习时间太短了,二是在这么多准大四都找不到实习,从实习时间和掌握技术层面,企业会优先看他们。 再说简历,其实985本+准大三到这水平的简历也很优秀了,要说的话,项目经历可以再优化一下,可以基本围绕采取STAR原则,分为项目概述、技术架构、技术亮点、实现结果,再发给AI润色一下。 最后说操作,准大三的话,如果想找实习那就多投,不过现在也7月中旬了,时间上已经略晚了。如果7月底实在找不到,也可以多刷点算法,多学点技术,这实习也不至于一定得有,当然有更好。
点赞 评论 收藏
分享
评论
2
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务