zoukankan      html  css  js  c++  java
  • LOJ #573. 「LibreOJ NOI Round #2」单枪匹马 线段树

    $f$ 函数暴力计算的话是 $O(n)$ 的(用一个 $frac{x}{y}$ 来保存每一步计算结果,然后依次合并)       

    我们将一段区间的结果写成 $frac{ax+by}{cx+dy}$ 的形式,初始时 $(x=0,y=1)$,然后这样的话就可以将区间分治,然后左右区间合并了.    

    注意合并的时候要把右区间的分子和分母调换一下.  

    code: 

    #include <bits/stdc++.h>    
    #define N 1000007   
    #define mod 998244353    
    #define ll long long  
    #define lson now<<1  
    #define rson now<<1|1   
    #define setIO(s) freopen(s".in","r",stdin)  ,freopen(s".out","w",stdout)  
    using namespace std;   
    char *p1,*p2,buf[100000];
    #define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
    int rd() {int x=0; char c=nc(); while(c<48) c=nc(); while(c>47) x=(((x<<2)+x)<<1)+(c^48),c=nc(); return x;}
    struct data 
    {
        ll a,b,c,d;   
        data(int v=0)  { a=1,b=v,c=0,d=1; }       
        data operator+(const data pp) const 
        {
            data nw;  
            data p=pp;   
            swap(p.a,p.c),swap(p.b,p.d);          
            nw.a=(a*p.a+b*p.c)%mod;   
            nw.b=(a*p.b+b*p.d)%mod;    
            nw.c=(c*p.a+d*p.c)%mod;   
            nw.d=(c*p.b+d*p.d)%mod;     
            return nw;    
        }     
    }s[N<<2];    
    void update(int l,int r,int now,int p,int v) 
    {
        if(l==r) 
        {
            s[now]=data(v);       
            return;  
        }
        int mid=(l+r)>>1;  
        if(p<=mid)  update(l,mid,lson,p,v);  
        else update(mid+1,r,rson,p,v);  
        s[now]=s[lson]+s[rson];    
    }        
    data query(int l,int r,int now,int L,int R) 
    {
        if(l>=L&&r<=R) return s[now];       
        int mid=(l+r)>>1;  
        if(L<=mid&&R>mid) 
            return query(l,mid,lson,L,R)+query(mid+1,r,rson,L,R);  
        else if(L<=mid) return query(l,mid,lson,L,R);  
        else return query(mid+1,r,rson,L,R);     
    }   
    void build(int l,int r,int now) 
    {
        if(l==r) return;  
        int mid=(l+r)>>1;  
        build(l,mid,lson),build(mid+1,r,rson);  
        s[now]=s[lson]+s[rson];   
    }
    int main() 
    { 
        // setIO("input");            
        int k,m,ty,n;            
        k=rd(),m=rd(),ty=rd();   
        n=k+m;  
        build(1,n,1);    
        for(int i=1;i<=k;++i)   
        {
            int x=rd();    
            update(1,n,1,i,x);    
        }                  
        int ansx=0,ansy=0;                
        for(int i=1;i<=m;++i) 
        {
            int op=rd(),x,l,r;  
            if(op==1) 
            {      
                x=rd(); 
                if(ty==1) x^=(ansx^ansy);      
                ++k,update(1,n,1,k,x);    
            }   
            else 
            {  
                l=rd(),r=rd();    
                if(ty==1) l^=(ansx^ansy);      
                if(ty==1) r^=(ansx^ansy);       
                data p=query(1,n,1,l,r);    
                ansx=p.b,ansy=p.d;    
                printf("%d %d
    ",ansx,ansy);  
            }
        }     
        return 0;
    }
    

      

  • 相关阅读:
    TL9000 电信业质量体系管理标准
    ISO/IEC 27001 信息安全管理体系认证
    编程要自学或报班这事你都想不明白, 那必然是你智商不够!
    Linux 计划任务 Crontab 笔记与总结(4)crontab 的日志
    中国象棋程序的设计与实现(一)--项目截图
    中国象棋程序的设计与实现(一)--项目截图
    C# XML 反序列化解析
    PHP开发实战权威指南-读书总结
    PHP开发实战权威指南-读书总结
    假如生活欺骗了你
  • 原文地址:https://www.cnblogs.com/guangheli/p/12635825.html
Copyright © 2011-2022 走看看