• 2018.7.20模拟考试


    这次的题...很水...然而还是差点爆零

    T1 题目简述:给定一个序列,求区间最大子段和(带修改操作)。

                 n<=500000,m<=100000

       解题思路:线段树维护即可。(GSS3原题...数据范围都不变...出题人好懒

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    #define INF 0x3f3f3f3f
    using namespace std;
    int n,m,a[500010];
    struct uio{
        uio(){lmx=rmx=mx=-INF;}
        int lmx,rmx,mx,sum;
    }tree[2000010];
    void pushup(int x)
    {
        int ls=(x<<1),rs=((x<<1)|1);
        tree[x].mx=max(tree[ls].rmx+tree[rs].lmx,max(tree[ls].mx,tree[rs].mx)); 
        tree[x].lmx=max(tree[ls].lmx,tree[ls].sum+tree[rs].lmx);
        tree[x].rmx=max(tree[rs].rmx,tree[rs].sum+tree[ls].rmx);
        tree[x].sum=tree[ls].sum+tree[rs].sum;
    }
    void build(int now,int l,int r)
    {
        if(l==r)
        {
            tree[now].mx=tree[now].lmx=tree[now].rmx=tree[now].sum=a[l];
            return;
        }
        int mid=(l+r)>>1;
        build((now<<1),l,mid);
        build(((now<<1)|1),mid+1,r);
        pushup(now);
    }
    void revise(int now,int l,int r,int to,int k)
    {
        if(l==r)
        {
            tree[now].mx=tree[now].lmx=tree[now].rmx=tree[now].sum=k;
            return;
        }
        int mid=(l+r)>>1;
        if(to<=mid) revise((now<<1),l,mid,to,k);
        else revise(((now<<1)|1),mid+1,r,to,k);
        pushup(now);
    }
    uio query(int now,int l,int r,int L,int R)
    {
        if(L<=l&&r<=R) return tree[now];
        int mid=(l+r)>>1;
        if(L>mid) return query(((now<<1)|1),mid+1,r,L,R);
        if(R<=mid) return query((now<<1),l,mid,L,R);
        if(L<=mid&&mid<R)
        {
            uio ans;
            uio a=query((now<<1),l,mid,L,R);
            uio b=query(((now<<1)|1),mid+1,r,L,R);
            ans.mx=max(a.rmx+b.lmx,max(a.mx,b.mx));
            ans.lmx=max(a.lmx,a.sum+b.lmx);
            ans.rmx=max(b.rmx,b.sum+a.rmx);
            ans.sum=a.sum+b.sum;
            return ans;
        }
    }
    int main()
    {
        freopen("BRS.in","r",stdin);
        freopen("BRS.out","w",stdout);
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        build(1,1,n);
        for(int i=1;i<=m;i++)
        {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            if(u==2) revise(1,1,n,v,w);
            if(u==1)
            {
                if(v>w) swap(v,w);
                printf("%d
    ",query(1,1,n,v,w).mx);
            }
        }
        return 0;
    }

    T2 题意简述:有n个格子,每次最多走k个,问走到第n格有多少种走法。答案对7777777取模。

                 1<=n<=2^31-1,1<=k<=10

       解题思路:一看n这么大,考虑矩阵加速。

                 发现递推过程类似斐波那契数列,因此构造矩阵如下。(以k=5为例)

    0 0 0 0 1
    0 1 0 0 1
    0 0 1 0 1
    0 0 0 1 1

                 然后求qpow(matrix.a,n)即可。

                 注:以下代码来自sdfzsyq大佬。(其实就是我懒...

    #include<iostream> 
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #define LL long long
    
    using namespace std;
    const int mod = 7777777;
    
    int n,k;
    
    struct Mat{
        LL a[15][15];
        Mat(){
            memset(a,0,sizeof(a));
        }
        Mat operator*(const Mat &h){
            Mat c;
            for(register int i=1;i<=k;i++)
                for(register int j=1;j<=k;j++)
                    for(register int o=1;o<=k;o++)
                        (c.a[i][j]+=(a[i][o]%mod*h.a[o][j]%mod))%=mod;
            return c;
        }
    }f,ans,st;
    
    inline void fast_pow(Mat A,int b){
        for(;b;b>>=1){
            if(b&1) st=st*A;
            A=A*A;
        }
    }
    
    int main(){
        freopen("fyfy.in","r",stdin);
        freopen("fyfy.out","w",stdout);
        scanf("%d%d",&k,&n);
        if(k==1){
            puts("1");
            return 0;
        }
        for(register int i=2;i<=k;i++)  f.a[i][i-1]=1;
        for(register int i=1;i<=k;i++)  f.a[i][k]=1;
        for(register int i=1;i<=k;i++)  st.a[i][i]=1;
        fast_pow(f,n);
        printf("%lld
    ",st.a[k][k]);
        return 0;
    }

    T3 题意简述:求矩形面积并。

                 n<=100,坐标数值绝对值<=10^8

       解题思路:扫描线。

                 由于数据太水,因此本题可以用O(n^2)水过。

                 坐在我旁边的ErkkiErkko大佬说n应该开到10^6。

                 如果按照ErkkiErkko大佬的数据范围,本题代码应加上线段树优化+卡常。

                 复杂度O(nlogn)。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    #define inf 100000001
    #define INF 0x3f3f3f3f
    #define ll long long
    using namespace std;
    ll n,ans,a[210],sec[210][110],sec1[210][110],vis[110];
    struct uio{
        ll l,r,u,d;
    }mat[110];
    struct oiu{
        ll u,d;
    }tmp[110];
    bool cmp(oiu x,oiu y)
    {
        if(x.u==y.u)
            return x.d>y.d;
        return x.u>y.u;
    }
    int main()
    {
        freopen("olddriver.in","r",stdin);
        freopen("olddriver.out","w",stdout);
        scanf("%lld",&n);
        for(ll i=1;i<=n;i++)
        {
            scanf("%lld%lld%lld%lld",&mat[i].l,&mat[i].d,&mat[i].r,&mat[i].u);
            a[i*2-1]=mat[i].l,a[i*2]=mat[i].r;
        }
        sort(a+1,a+1+2*n);
        ll num=unique(a+1,a+1+2*n)-a-1;
        for(ll i=1;i<=n;i++)
        {
            ll u=lower_bound(a+1,a+1+num,mat[i].l)-a;
            sec[u][++sec[u][0]]=i,sec1[u][++sec1[u][0]]=mat[i].l;
            ll v=lower_bound(a+1,a+1+num,mat[i].r)-a;
            sec[v][++sec[v][0]]=i,sec1[v][++sec1[v][0]]=mat[i].r;
        }
        for(ll i=1;i<=200;i++)
        {
            memset(tmp,0,sizeof(tmp));
            ll cnt=0,num=0;
            ll j=1;
            while(sec[i][j]!=0)
            {
                if(!vis[sec[i][j]])
                    vis[sec[i][j]]=1;
                else vis[sec[i][j]]=0;
                j++;
            }
            for(ll k=1;k<=n;k++)
                if(vis[k])
                    tmp[++cnt].u=mat[k].u,
                    tmp[cnt].d=mat[k].d;
            sort(tmp+1,tmp+1+cnt,cmp);
            ll mu=tmp[1].u,md=tmp[1].d;
            for(ll k=2;k<=cnt;k++)
            {
                if(tmp[k].u<md)
                    num-=md-tmp[k].u;
                md=min(md,tmp[k].d);
            }
            num+=mu-md;
            ans+=num*(sec1[i+1][1]-sec1[i][1]);
        }
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    Transfer: Javascript实现网页水印(非图片水印)
    VirtualPathUtility class from MSDN
    深入理解Flink 系统内部消息传递的exactly once语义
    深入理解Flink EndtoEnd ExactlyOnce语义
    深入理解Flink Metrics的内部结构
    深度优化sql 查询, 提升性能一百倍是什么概念?
    asp.net mvc+asp.net webform: a way of RIA + RAD
    使用scheduled task, 让电脑音乐伴你入眠
    A small breaking change in IE8 causing big pain in the ass: the default type of button element
    tsql 和 clr 的性能实测比对
  • 原文地址:https://www.cnblogs.com/water-radish/p/9342270.html
Copyright © 2020-2023  润新知