zoukankan      html  css  js  c++  java
  • 还教室

    【问题描述】

    还记得NOIP 2012提高组Day2中的借教室吗?时光飞逝,光阴荏苒,两年
    过去了,曾经借教室的同学们纷纷归还自己当初租借的教室。请你来解决类似于
    借教室的另一个问题。
    在接受借教室请求的n天中,第i天剩余的教室为ai个。作为大学借教室服
    务的负责人,你需要完成如下三种操作共m次:
    l天到第r天,每天被归还d个教室。
    询问第l天到第r天教室个数的平均数。
    询问第l天到第r天教室个数的方差。

    【输入格式】

    第一行包括两个正整数nm,其中n为借教室的天数,m 为操作次数。
    接下来一行,共包含n个整数,第i个整数表示第i天剩余教室数目为ai个。
    接下来m行,每行的第一个整数为操作编号(只能为123),接下来
    包含两个正整数lr,若操作编号为1,则接下来再包含一个正整数d

    【输出格式】

    对于每个操作2和操作3,输出一个既约分数(分子与分母互质)表示询问
    的答案(详见样例)。若答案为0,请输出“0/1”(不含引号)。

    【样例输入】

    5 4
    1 2 3 4 5
    1 1 2 3
    2 2 4
    3 2 4
    3 1 5

    【样例输出】

    4/1
    2/3
    14/25

    【数据范围】

    对于全部测试数据满足:1 ≤ l ≤ r ≤ n,0 ≤ ai ≤ 10,1 ≤ d ≤ 3,操作 1 的数量
    不超过 10%。注意:ai和 d 的范围很小及操作 1 数量很少的原因是为了保证答案
    的分子不会很大,以防止答案的分子溢出 64 位整数的范围,这与题目做法无关。

    【题解】

    一看这种描述如此套路的题目就知道是数据结构题。
    相当于维护区间加法,区间平均值,区间方差,这个可以用线段树维护。
    平均值可以由区间和除以区间长度维护
    区间方差,即∑(x ̅-xi)2**,可以转化为**(∑(x2) *len-(∑x)2)/(len2) 其中len是区间的长度
    所以,只需要维护∑(x^2)和∑(x),也就是区间和以及区间平方和,就可以了。
    剩下的就是线段树的事情了。
    (调了2个半小时,还写了对拍,最后发现有一个地方忘long long了......)

    【代码】

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #include<queue>
    #include<set>
    using namespace std;
    #define f(i,n) for(int i=1;i<=(n);i++)
    #define ll long long
    #define INF 1<<30
    #define N 100010
    int read()
    {
        int x=0,f=1;char c=getchar();
        while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
        while( isdigit(c)){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    int a[N];
    ll maxn[3*N],sum[3*N],minn[3*N],sumf[3*N],tag[3*N];
    int n,q;
    int z,ql,qr;
    ll addi;
    void pushup(int o,int l,int r)
    {
        int lo=2*o,ro=2*o+1,m=(l+r)>>1;
        sum[o]=sum[lo]+sum[ro];
        maxn[o]=max(maxn[lo],maxn[ro]);
        minn[o]=min(minn[lo],minn[ro]);
        sumf[o]=sumf[lo]+sumf[ro];
    }
    void dingyi(int o,int l,int r)
    {
        if(l==r)
        {
            sum[o]=maxn[o]=minn[o]=a[l];
            sumf[o]=a[l]*a[l];
            return;
        }
        int lo=2*o,ro=2*o+1,m=(l+r)>>1;
        dingyi(lo,l,m);
        dingyi(ro,m+1,r);
        pushup(o,l,r);
    }
    void pushdown(int o,int l,int r)
    {
        if(l==r)return;
        int lo=2*o,ro=2*o+1,m=(l+r)>>1;
        if(tag[o])
        {
            tag[lo]+=tag[o];
            tag[ro]+=tag[o];
            sumf[lo]+=(ll)(m-l+1)*tag[o]*tag[o]+(ll)2*tag[o]*sum[lo];
            sumf[ro]+=(ll)(r-m)*tag[o]*tag[o]+(ll)2*tag[o]*sum[ro];
            sum[lo]+=(ll)(m-l+1)*tag[o];
            sum[ro]+=(ll)(r-m)*tag[o];
            maxn[lo]+=tag[o];
            maxn[ro]+=tag[o];
            minn[lo]+=tag[o];
            minn[ro]+=tag[o];
        }
        tag[o]=0;
    }
    void add(int o,int l,int r)
    {
        if(l>=ql&&r<=qr)
        {
            sumf[o]+=(ll)(r-l+1)*addi*addi+2ll*addi*sum[o];
            sum[o]+=(ll)(r-l+1)*addi;
            maxn[o]+=addi;
            minn[o]+=addi;
            tag[o]+=addi;
            return;
        }
        pushdown(o,l,r);
        int lo=2*o,ro=2*o+1,m=(l+r)>>1;
        if(ql<=m)add(lo,l,m);
        if(qr>m)add(ro,m+1,r);
        pushup(o,l,r);
    }
    ll qsum=0,qsumf=0;
    void query(int o,int l,int r)
    {
        if(l>=ql&&r<=qr)
        {
            qsum+=sum[o];
            qsumf+=sumf[o];
            return;
        }
        int lo=2*o,ro=2*o+1,m=(l+r)>>1;
        pushdown(o,l,r);
        if(ql<=m)query(lo,l,m);
        if(qr>m)query(ro,m+1,r);
        pushup(o,l,r);
    }
    ll xj(ll a,ll b)
    {
        if(b==0)return a;
        return xj(b,a%b);
    }
    void qj(ll a,ll b)
    {    
        ll s=xj(a,b);
        printf("%lld/%lld
    ",a/s,b/s);
    }
    int main()
    {
        n=read();
        q=read();
        f(i,n)a[i]=read();
        dingyi(1,1,n);
        f(i,q)
        {
            z=read();
            ql=read();
            qr=read();
            if(z==1)
            {
                scanf("%lld",&addi);
                if(addi==0)continue;
                add(1,1,n);
            }
            if(z==2)
            {
                qsum=0;
                qsumf=0;
                query(1,1,n);
                qj(qsum,qr-ql+1);
            }
            if(z==3)
            {
                qsum=0;
                qsumf=0;
                query(1,1,n);
                //cout<<"qsum "<<qsum<<" qsumf "<<qsumf<<endl;        
                qj(qsumf*(ll)(qr-ql+1)-qsum*qsum,(ll)(qr-ql+1)*(ll)(qr-ql+1));
            }
        }
    }
    
  • 相关阅读:
    actionBar-进入界面闪烁问题解决
    softInputMode- 软件盘的设置
    LinearLayout -设置负值属性
    launcher- 第三方应用图标替换
    resource-color 的引用
    java学习笔记——IO流部分
    二进制基础
    java学习笔记——IO部分(遍历文件夹)
    Java线程:线程的同步与锁
    AWT与Swing的区别
  • 原文地址:https://www.cnblogs.com/qwerfcxs/p/7810737.html
Copyright © 2011-2022 走看看