程序中 个数查询函数 如何工作

P3586 [POI2015] LOG

张心博harry @ 2025-01-10 18:34:33

对于一个查询超过 s 的元素个数操作,我会将他的答案乘以 s,因为“询问操作转化为比 s 大的都按照 s 算求和”。

long long qryn(int x){
    long long ans=0;
    while(x){
        ans+=tn[x];
        x-=lowbit(x);
    }
    return ans;
}

然而当我尝试输出样例中 qryn(len) 时,他的答案是 0 。(len 是离散化数组的大小,即最大值。)

有趣的是:这份代码竟然顺利通过样例并且 AC 了。

这说明(且经过我的验证) qryn(v-1) 是负数。(v 就是 s 离散化后的数值)

请问这是为什么?

谢谢%%%

贴上完整代码,可能是其他版块出现问题,具体已在文中标注。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define int long long
#define lowbit(i) (i&(-i))

using namespace std;

const int N=1e6+10;

int n,m;
int len;//离散化去重后的长度
long long a[N];//题面中序列的数值在离散化数组中的位置
long long ts[N<<1],tn[N<<1];//ts统计和,tn统计数字个数。

void adds(int x,long long z){ //加入新数字
    while(x<=len){
        ts[x]+=z;
        tn[x]++;  //我在这
        x+=lowbit(x);
    }
    return ;
}

void deln(int x,long long z){ //删除旧数
    while(x<=len){
        ts[x]-=z;
        tn[x]--;  //我在这
        x+=lowbit(x);
    }
    return ;
}

long long qrys(int x){ //求和
    long long ans=0;
    while(x){
        ans+=ts[x];
        x-=lowbit(x);
    }
    return ans;
}
long long qryn(int x){ //求个数
    long long ans=0;
    while(x){
        ans+=tn[x];
        x-=lowbit(x);
    }
    return ans;
}

struct question{
    int op;
    int x;
    long long z;
}q[N];

long long lsh[N]; //离散化数组
int ef(long long x){
    int l=1,r=len,mid;

    while(l<r){
        mid=(l+r+1)>>1;

        if(lsh[mid]>x){
            r=mid-1;
        }
        else{
            l=mid;
        }
    }

    return l;
}

signed main(){

    scanf("%lld%lld",&n,&m);

    for(int i=0;i<=n;++i){
        a[i]=1;
        adds(1,0);
    }

    char opp;
    lsh[1]=0;
    for(int i=1;i<=m;++i){
        scanf("\n%c%lld%lld",&opp,&q[i].x,&q[i].z);//进行离线

        if(opp=='U') q[i].op=0;
        else q[i].op=1;

        lsh[i+1]=q[i].z;
    }

    sort(lsh+1,lsh+m+2);
    len=unique(lsh+1,lsh+m+2)-lsh-1;

    int v;
    long long ans;
    for(int i=1;i<=m;++i){
        v=ef(q[i].z);

        if(!q[i].op){
            deln(a[q[i].x],lsh[a[q[i].x]]);
            adds(v,q[i].z);
            a[q[i].x]=v;
        }
        else{
            ans=qrys(v-1);//首先求小于 s 的数字和。
            ans+=(qryn(len)-qryn(v-1))*q[i].z; //然后大于等于 s 的都按 s 算。
//          cout<<qryn(v-1)<<endl;  //////////////////////////////////////////////就是这一行,他是0
//          cout<<qryn(v-1)<<endl;  //////////////////////////////////////////////就是这一行,他是负数
            if(ans>=q[i].x*q[i].z){
                printf("TAK\n");
            }
            else{
                printf("NIE\n");
            }
        }

    }

    return 0;
}

谢谢!/bx


by 张心博harry @ 2025-01-10 18:37:29

//      cout<<qryn(n)<<endl;  ///////////////////////////////////就是这一行,他是0
//      cout<<qryn(v-1)<<endl; //////////////////////////////////就是这一行,他是负数

by yi_hr @ 2025-01-10 18:48:57

我是奶龙


|