zoukankan      html  css  js  c++  java
  • bzoj4105: [Thu Summer Camp 2015]平方运算

    填坑

    我不知道怎么算的,但是所有环的LCM数不会超过60

    然后用线段树维护这个东西,每个节点记录子树内的循环节

    没到循环节的暴力枚举

    复杂度是nlogn再乘以循环节长度

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    #include<vector>
    
    #define lc (now<<1)
    #define rc (now<<1|1)
    #define mid (ql+qr)/2
    using namespace std;
    typedef long long LL;
    const int _=1e2;
    const int maxn=1e5+_;
    const int maxp=1e4+_;
    const int maxh=62+10;
    const int mbit=(1<<17)+_;
    int gcd(int a,int b){if(a==0)return b;return gcd(b%a,a);}
    int lcm(int a,int b){return a/gcd(a,b)*b;}
    
    int nxt[maxp];bool inh[maxp];int tim,v[maxp];
    void init(int p)
    {
        for(int i=0;i<p;i++)nxt[i]=i*i%p;
        tim=0;
        for(int i=0;i<p;i++)
            if(v[i]==0)
            {
                v[i]=++tim;
                for(int k=nxt[i];;k=nxt[k])
                {
                    if(v[k]==tim)
                    {
                        inh[k]=true;
                        for(int u=nxt[k];u!=k;u=nxt[u])inh[u]=true;
                        break;
                    }
                    if(v[k]>0)break;
                    v[k]=tim;
                }
            }
    }
    
    //--------------------------------------yu---------------------------------------------------
    
    struct hh
    {
        int len,pos,h[maxh];
        hh(){}
        int insert(int d)
        {
            if(inh[d])
            {
                len=0;pos=1;h[++len]=d;
                for(int k=nxt[d];k!=d;k=nxt[k])h[++len]=k;
                return 0;
            }
            return -1;
        }
        void merge(hh h1,hh h2)
        {
            len=lcm(h1.len,h2.len);pos=1;
            for(int k=1,i=h1.pos,j=h2.pos;k<=len;k++,i=i%h1.len+1,j=j%h2.len+1)
                h[k]=h1.h[i]+h2.h[j];
        }
        int ad(int b){pos=(pos+b-1)%len+1;return h[pos];}
    };
    struct trnode{int sum,la;hh h;};int w[maxn];
    struct Segtree
    {
        trnode tr[2*mbit];
        Segtree(){}
        void update(int now)
        {
            tr[now].sum=tr[lc].sum+tr[rc].sum;
            if(tr[lc].la!=-1&&tr[rc].la!=-1)
            {
                tr[now].la=0;
                tr[now].h.merge(tr[lc].h,tr[rc].h);
            }
            else tr[now].la=-1;
        }
        void pushdown(int now)
        {
            if(tr[now].la<=0)return ;
            tr[lc].sum=tr[lc].h.ad(tr[now].la),tr[lc].la=(tr[lc].la+tr[now].la-1)%tr[lc].h.len+1;
            tr[rc].sum=tr[rc].h.ad(tr[now].la),tr[rc].la=(tr[rc].la+tr[now].la-1)%tr[rc].h.len+1;
            tr[now].la=0;
        }
        void bt(int now,int ql,int qr)
        {
            if(ql==qr){tr[now].sum=w[ql],tr[now].la=tr[now].h.insert(w[ql]);return ;}
            bt(lc,ql,mid),bt(rc,mid+1,qr),update(now);
        }
        void change(int now,int ql,int qr,int l,int r)
        {
            if(ql==l&&qr==r&&tr[now].la!=-1){tr[now].sum=tr[now].h.ad(1);tr[now].la++;return ;}
            if(ql==qr){tr[now].la=tr[now].h.insert(nxt[tr[now].sum]),tr[now].sum=nxt[tr[now].sum];return ;}
            pushdown(now);
                 if(r<=mid)  change(lc,ql,mid,l,r);
            else if(mid+1<=l)change(rc,mid+1,qr,l,r);
            else change(lc,ql,mid,l,mid),change(rc,mid+1,qr,mid+1,r);
            update(now);
        }
        int getsum(int now,int ql,int qr,int l,int r)
        {
            if(ql==l&&qr==r)return tr[now].sum;
            pushdown(now);
                 if(r<=mid)  return getsum(lc,ql,mid,l,r);
            else if(mid+1<=l)return getsum(rc,mid+1,qr,l,r);
            else return getsum(lc,ql,mid,l,mid)+getsum(rc,mid+1,qr,mid+1,r);
        }
    }S;
    
    //---------------------------------data structure---------------------------------------------
    
    int main()
    {
        freopen("a.in","r",stdin);
        freopen("a.out","w",stdout);
        int n,Q,p;
        scanf("%d%d%d",&n,&Q,&p);
        init(p);
        
        for(int i=1;i<=n;i++)scanf("%d",&w[i]);
        S.bt(1,1,n);
        
        int op,x,y;
        while(Q--)
        {
            scanf("%d%d%d",&op,&x,&y);
            if(op==0)S.change(1,1,n,x,y);
            else printf("%d
    ",S.getsum(1,1,n,x,y));
        }
        
        return 0;
    }
  • 相关阅读:
    lucene .NET 搜索图片 功能实现
    (转)权威支持: 选择正确的 WebSphere 诊断工具
    (转)WebSphere 中池资源调优
    (转)使用 DB2 HADR 选择用于灾难恢复的 SUPERASYNC 模式
    (转) DB2 HADR
    (转)DB2 HADR 监控详解
    (转)python高级FTP
    (转)Python的web服务器
    (转)python通过paramiko实现,ssh功能
    (转)request模拟知乎登录(无验证码机制
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/10446726.html
Copyright © 2011-2022 走看看