LOJ #573. 「LibreOJ NOI Round #2」单枪匹马 线段树

白昼怎懂夜的黑 提交于 2020-04-05 15:33:21

$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\n",ansx,ansy);  
        }
    }     
    return 0;
}

  

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!