• Coder HDU


    Coder HDU - 4288

    题意:你有n次操作,每次可以往集合里插入元素,删除元素,然后如果是求和操作的话,是求升序排序的情况下,pos%5==3的位置的数之和。

    思路:因为要开权值线段树数很大,所以先把操作离线把要用到的数都离散化了,然后线段树维护的是区间数的个数num和区间位置%5==i的位置的数之和sum[i],我们最后查询的时候要的是根节点的sum[3],这题的关键就是这个pushup里的更新sum【i】值。

    for(int i=0;i<=4;i++)
            sum[rt][i]=sum[ls][i]+sum[rs][((i-num[ls])%5+5)%5];

    因为求根节点的sum[3]的时候说不定用的是右儿子的sum[0,1,2,3,4]里的哪个,所有对节点都要维护sum[0~4],然后sum[rt][i]要直接加上左儿子的sum[ls][i]是毋庸置疑的,关键是要找到rs节点对应区间里的数放到rt节点区间里时位置%5==i的位置的数之和是多少假设这个位置是pos,那么有(ls.num+pos)%5==i,我们要的就是满足条件的pos位置的数之和,然后有

    同余式相加:若a≡b(mod m),c≡d(mod m),则a+c≡b+d(mod m); 减法也成立
    同余式相乘:若a≡b(mod m),c≡d(mod m),则ac≡bd(mod m)。

    所有可以得到pos同余(i-ls.num) 在mod5情况下,那么就有pos%5==(i-ls.num)%5,所以要的就是右儿子的sum[(i-ls.num)%5]。由于pos%5==(i-ls.num)%5这个是数学上相等,到了c++里面可以就不一定相等了因为数学里(-20)%11==2,但是c++里(-20)%11==-9,所以写代码的时候还要考虑(i-ls.num)%5为负数的情况,那么((i-ls.num)%5+5)%5就可以避免负数的情况了,所以应该是加sum[((i-num[ls])%5+5)%5]。

    #include<stdio.h>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ls rt<<1
    #define rs (rt<<1)+1
    #define ll __int64
    #define fuck(x) cout<<#x<<"     "<<x<<endl;
    const int maxn=1e5+20;
    int d[4][2]={1,0,-1,0,0,1,0,-1};
    int num[maxn<<2],n,vcnt;
    ll sum[maxn<<2][5],lsh[maxn];
    struct node
    {
        char op[10];
        ll val;
    }q[maxn];
    inline int getid(ll x)
    {
        return lower_bound(lsh+1,lsh+vcnt+1,x)-lsh;
    }
    void pushup(int rt)
    {
        num[rt]=num[ls]+num[rs];
        for(int i=0;i<=4;i++)
            sum[rt][i]=sum[ls][i]+sum[rs][((i-num[ls])%5+5)%5];
    }
    void update(int rt,int L,int R,int pos,int val)
    {
        if(L==R)
        {
            if(val==1)
            {
                num[rt]=1;
                sum[rt][1]=1LL*lsh[pos];
            }
            else
            {
                num[rt]=0;
                sum[rt][1]=0LL;
            }
            return ;
        }
        int mid=(L+R)>>1;
        if(pos<=mid)
            update(ls,L,mid,pos,val);
        else
            update(rs,mid+1,R,pos,val);
        pushup(rt);
    }
    int main()
    {
        while(scanf("%d",&n)!=EOF)
        {
            vcnt=0;
            memset(num,0,sizeof(num));
            memset(sum,0,sizeof(sum));
            for(int i=1;i<=n;i++)
            {
                scanf("%s",q[i].op);
                if(q[i].op[0]=='a'||q[i].op[0]=='d')
                    scanf("%I64d",&(q[i].val)),lsh[++vcnt]=q[i].val;
            }
            sort(lsh+1,lsh+vcnt+1);
            vcnt=unique(lsh+1,lsh+vcnt+1)-lsh-1;
            for(int i=1;i<=n;i++)
                if(q[i].op[0]=='a')
                    update(1,1,vcnt,getid(q[i].val),1);
                else
                    if(q[i].op[0]=='d')
                        update(1,1,vcnt,getid(q[i].val),0);
                    else
                        printf("%I64d
    ",sum[1][3]);
        }
        return 0;
    }
    
  • 相关阅读:
    iOS:图片相关(19-05-09更)
    iOS:文字相关(19-01-08更)
    iOS:通信录(完成)(18-01-18更)
    Swift 中的Closures(闭包)详解
    Swift 中的高阶函数和函数嵌套
    Swift API设计原则
    Swift下CoreData的使用
    iOS 使用贝塞尔曲线绘制路径
    iOS CALayer使用
    iOS 多线程的使用
  • 原文地址:https://www.cnblogs.com/eason9906/p/11754747.html
Copyright © 2020-2023  润新知