zoukankan      html  css  js  c++  java
  • P5358 [SDOI2019]快速查询 思维题

    题意:

    戳这里

    分析:

    • 暴力

    随便来个数据结构直接模拟,但是操作量达到了 (1e7) 级别,也就是说单个操作必须做到 (O(1))

    • 正解

    观察发现只有全局操作和单点操作,所以用到了一个小 (trick) 就是维护一个全局标记,然后对于单点进行修改,这样可以做到 (O(1)) 进行全局修改,然后对于单点修改操作转化一下也可以做到 (O(1))

    具体来说就是:

    维护一个全局乘标记 (mul) 全局加标记 (add) 全局赋值标记 (tag) 全局和 (sum) 时间戳 (lst) 每一个点最近第一次单点赋值 (tim[])

    这样每一个位置的值等价于 (v[x]*mul+add) ,然后我们开始分操作考虑怎么维护

    1. 单点赋值 (val)

    我们逆向推出 (v[pos]) 应该变成什么 (v[pos]*mul+add=val o v[pos]=(val-add) imes inv(mul)) 然后直接修改 (v[pos]) 的值就好了

    1. 全局加 (val)

    (add=add+val sum=sum+val*n)

    1. 全局乘 (val)

    (add=add*val mul=mul*val sum=sum*val) 注意由于 (0) 没有逆元所以乘 (0) 的操作要看成全局赋值 (0)

    1. 全局赋值 (val)

    (tag=val mul=1 add=0 sum=val*n) 同时更新一下 (lst)

    1. 单点查询

    分情况讨论一下

    (a) : 上一次全局修改在这一个点的单点赋值之前,也就是说全局赋值被覆盖了,那么 (ans=v[pos]*mul+add)

    (b) : 上一次全局修改在单点修改之后,也就是说此时的值应该为全局赋值标记 (ans=tag*mul+add)

    1. 全局查询

    直接上 (sum)

    由于这题读入比较诡异,所以我们可以离散化出修改的点的坐标,这样就可以开的下 (v,tim)

    tip:

    诡异的读入要求 (a,b) 必须开成 (long long) 不然两个 (int) 相乘直接爆炸,不要问我怎么知道的/kk

    代码:

    #include<bits/stdc++.h>
    
    using namespace std;
    
    namespace zzc
    {
        long long read()
        {
            long long x=0,f=1;char ch=getchar();
            while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
            while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
            return x*f;
        }
    
        const int maxn = 1e5+5;
        const long long mod = 1e7+19;
        long long n,qt,cnt,t,lst,sum,ans,mul,add,tag;
        long long d[maxn],tim[maxn],inv[mod+5],v[maxn];
        struct query
        {
            long long opt,pos,val;
        }q[maxn];
        
        void init()
        {
            inv[1]=inv[0]=1;
            for(int i=2;i<mod;i++) inv[i]=inv[mod%i]*(mod-mod/i)%mod;
            n=read();qt=read();
            for(int i=1;i<=qt;i++)
            {
                q[i].opt=read();
                if(q[i].opt==1||q[i].opt==5) q[i].pos=read(),d[++cnt]=q[i].pos;
            	if(q[i].opt<=4) q[i].val=read(),q[i].val=(q[i].val%mod+mod)%mod;
            	if(q[i].opt==3&&q[i].val==0) q[i].opt=4;
            }
            sort(d+1,d+cnt+1);
            cnt=unique(d+1,d+cnt+1)-d-1;
            for(int i=1;i<=qt;i++) if(q[i].opt==1||q[i].opt==5) q[i].pos=lower_bound(d+1,d+cnt+1,q[i].pos)-d;
            mul=1;tag=0;add=0;lst=0;
        }
    
        void work()
        {
            long long a,b,id;
            init();
            t=read();
            for(int i=1;i<=t;i++)
            {
                a=read();b=read();
                for(int j=1;j<=qt;j++)
                {
                    id=(a+j*b)%qt+1;
                    if(q[id].opt==1)
                    {
                        if(tim[q[id].pos]<=lst) sum=(sum-(tag*mul%mod+add)%mod+mod)%mod;
                        else sum=(sum-(v[q[id].pos]*mul%mod+add)%mod+mod)%mod;
                        sum=(sum+q[id].val)%mod;
                        tim[q[id].pos]=(i-1)*qt+j;
                        v[q[id].pos]=(q[id].val-add+mod)%mod*inv[mul]%mod;
                    }
                    else if(q[id].opt==2)
                    {
                        add=(add+q[id].val)%mod;
                        sum=(sum+n*q[id].val%mod)%mod;
                    }
                    else if(q[id].opt==3)
                    {
                        add=add*q[id].val%mod;
                        mul=mul*q[id].val%mod;
                        sum=sum*q[id].val%mod;
                    }
                    else if(q[id].opt==4)
                    {
                        lst=(i-1)*qt+j;
                        tag=q[id].val;
                        mul=1;add=0;
                        sum=n*q[id].val%mod;
                    }
                    else if(q[id].opt==5)
                    {
                        if(tim[q[id].pos]<=lst) ans=(ans+(tag*mul%mod+add)%mod)%mod;
                        else ans=(ans+(v[q[id].pos]*mul%mod+add)%mod)%mod;
                    }
                    else if(q[id].opt==6)
                    {
                        ans=(ans+sum)%mod;
                    }
    //                printf("#%d: id=%d mul=%d add=%d tag=%d sum=%lld %lld
    ",(i-1)*qt+j,id,mul,add,tag,sum,ans);
                }
            }
            printf("%lld
    ",ans%mod);
        }
    
    }
    
    int main()
    {
        zzc::work();
        return 0;
    }
    
  • 相关阅读:
    伪静态规则写法RewriteRule-htaccess详细语法使用
    事务的操作
    layer 模版使用
    追加下拉框的自动生成
    PHP自动生成前端的表单框架
    MySQL高效获取记录总数
    引用JS表单验证大全 以后方便查看用
    关于left join连接查询 两张表里有同名字段的问题
    详解clientHeight、offsetHeight、scrollHeight
    php防止SQL注入详解及防范
  • 原文地址:https://www.cnblogs.com/youth518/p/14257470.html
Copyright © 2011-2022 走看看