[2018年11月7日] luogu NOIPウォームアップブラシや考え方の問題

A.間隔変動

- セグメントツリー

実際には、これは質問の弱いバージョンです。

P1471の分散

この問題は、クエリ間隔を変更するだけで、単一のポイントを必要とします

マーク怠惰ではない、直接シングルポイントを変更

分散を計算することが重要です

\(S ^ 2 = \ FRAC {(a_1- \上線{})^ 2+(a_2- \上線{})^ 2+(a_3- \上線{})^ 2 ... +(a_n- \上線{})^ 2} {N} = \)

= \(\ FRAC {N \上線{} ^ 2-2 \上線{}(A_1 + A_2 + A_3 + ... A_N)+ A_1 ^ 2 + A_2 ^ 2 + A_3 ^ 2 + ... + A_N ^ 2} { N} \)

(\ \ {A_1 + A_2 + A_3 + ... + A_N} {N} = \上線{} \ FRAC \ため)

\(\したがって、S ^ 2 = \ FRAC {A_1 ^ 2 + A_2 ^ 2 + A_3 ^ 2 + ... + A_N ^ 2} {N} - \上線{N} ^ 2 \)

したがって、我々は維持する必要が間隔と同様の間隔の正方形をして、正常分散を計算することができるようになります

#define lson o<<1
#define rson o<<1|1
const int N=1e5+10,mod=1e9+7;

struct tree{
    int l,r;
    int sum,sum_2;
}t[N<<2];

int n,m;
int val[N];

inline void pushup(int o){
    t[o].sum=(t[lson].sum+t[rson].sum)%mod;
    t[o].sum_2=(t[lson].sum_2+t[rson].sum_2)%mod;
}

inline void build(int o,int l,int r){
    t[o].l=l,t[o].r=r;
    if(l==r){
        t[o].sum=val[l];
        t[o].sum_2=1ll*val[l]*val[l]%mod;
        return ;
    }
    int mid=(l+r)>>1;
    build(lson,l,mid);
    build(rson,mid+1,r);
    pushup(o);
}

inline void change(int o,int pos,int k){
    int l=t[o].l,r=t[o].r;
    if(pos==l && pos==r){
        t[o].sum=k;
        t[o].sum_2=1ll*k*k%mod;
        return ;
    }
    int mid=(l+r)>>1;
    if(pos<=mid)
        change(lson,pos,k);
    else 
        change(rson,pos,k);
    pushup(o);
}

inline int query_sum(int o,int x,int y){
    int l=t[o].l,r=t[o].r;
    if(x<=l && r<=y){
        return t[o].sum;
    }
    int mid=(l+r)>>1;
    int res=0;
    if(x<=mid)(res+=query_sum(lson,x,y))%=mod;
    if(mid<y)(res+=query_sum(rson,x,y))%=mod;
    return res%mod;
}

inline int query_sum_2(int o,int x,int y){
    int l=t[o].l,r=t[o].r;
    if(x<=l && r<=y){
        return t[o].sum_2;
    }
    int mid=(l+r)>>1;
    int res=0;
    if(x<=mid)(res+=query_sum_2(lson,x,y))%=mod;
    if(mid<y)(res+=query_sum_2(rson,x,y))%=mod;
    return res%mod;
}

inline int ksm(int a,int k,int mod){
    a%=mod,k%=mod;
    int res=1;
    for(;k;k>>=1){
        if(k&1)res=1ll*res*a%mod;
        a=1ll*a*a%mod;
    } 
    return res;
}

#undef int
int main(){
#define int long long
//  freopen("a.in","r",stdin);
    rd(n),rd(m);
    rep(i,1,n)rd(val[i]);
    build(1,1,n);
    while(m--){
        int op,x,y,k;
        rd(op);
        if(op==1){
            rd(x),rd(k);
            change(1,x,k);
        }
        else if(op==2){
            rd(x),rd(y);
            /*
            方差=(a1^2+a2^2+...+an^2)/n  -  a_ba^2; 
            */
            int len=ksm(y-x+1,mod-2,mod);
            
            int sum=query_sum(1,x,y)%mod;
            int ba=sum*len%mod;
            int ave=ba*ba%mod;
            
            int sum_2=query_sum_2(1,x,y)%mod;
            sum_2=sum_2*len%mod; 
            
            int ans=sum_2-ave;
            
            while(ans<0)ans+=mod;
            printf("%lld\n",ans);
        }
    }
    return 0;
}

B.クライマー

- アナログ

ああああのような距離のシーケンスを計算する行のちょうど高さ、水であります

#include<bits/stdc++.h>
using namespace std;

template <typename T>inline void rd(T &x){x=0;char c=getchar();int f=0;while(!isdigit(c)){f|=c=='-';c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}x=f?-x:x;} 
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define dwn(i,a,b) for(int i=a;i>=b;--i)
#define mem(a,b) memset(a,b,sizeof(a))
#define ee(i,u) for(int i=head[u];i;i=e[i].next)

const int N=5e4+10;

struct data{
    int x,y,z;
    bool operator < (const data &rhs)const{
        return z<rhs.z;
    }
}p[N];

double dist(int a,int b){
    return sqrt((p[a].x-p[b].x)*(p[a].x-p[b].x)+(p[a].y-p[b].y)*(p[a].y-p[b].y)+(p[a].z-p[b].z)*(p[a].z-p[b].z));
}

int n;

int main(){
    rd(n);
    rep(i,1,n){
        rd(p[i].x),rd(p[i].y),rd(p[i].z);
    }
    sort(p+1,p+n+1);
    double ans=0.000;
    rep(i,1,n-1){
        ans+=dist(i,i+1);
    }
    printf("%.3lf",ans);
    return 0;
}

C.ムカデ

- 間隔は、数学記号を入れてDP

\(F [i]は[J ] \) 最大値が分割された、J + 1つの値の排他的論理和の項を考慮i番目の位置を表します

ここでは、セグメントJ + 1つのkの列挙があるので、注意することをいくつかの「^」記号を置くことができるので、mの最初のマイナスを始め、

その後、間隔DPは、番号を列挙^が配置され、\(F [I] [J] = MAX(F [I]、[J]、F [K-1] [-J 1] + SUM [I] \ XOR \和[K-1 ])\)

int f[1010][110];
int n,m;
int sum[1010];

int main(){
    rd(n),rd(m);
    --m;
    rep(i,1,n){
        int x;rd(x);
        sum[i]=sum[i-1]^x;
        f[i][0]=sum[i];
    }
    rep(i,1,n)
        rep(j,1,min(i-1,m))
            rep(k,1,i)
                f[i][j]=max(f[i][j],f[k-1][j-1]+(sum[k-1]^sum[i]));
    printf("%d\n",f[n][m]);
    return 0;
}

D.浮動鴨

- トポロジカル整列

質問の意味することは明らかである:の姿を見つける最大のリングを

ソートトポロジリングを使用して要求

環上の点はトポロジー的ソートを残り後、言うことであるソート、に参加しないようにトポロジカルソート0度の始点からたびに、リング上の点の程度ので、ゼロではありませんエッジや点は、環の構成です。

だから我々は最大のリングを記録し、再び各環に直接スキャンできるということ以上です。

const int N=1e5+10;

struct Edge{
    int v,w,next;
}e[N];

int head[N],edge_num;
inline void adde(int u,int v,int w){
    e[++edge_num]=(Edge){v,w,head[u]};
    head[u]=edge_num;
}

int n,ans=0;
int deg[N];

queue<int>q;
inline void topo_sort(){
    while(!q.empty()){
        int u=q.front();q.pop();
        ee(i,u){
            int v=e[i].v;
            if(--deg[v]==0)q.push(v);
        } 
    }
}

inline void get_ring(){
    int res=0;
    while(!q.empty()){
        int u=q.front();q.pop();
        ee(i,u){
            int v=e[i].v,w=e[i].w;
            if(deg[v]==0)continue;
            deg[v]--;
            res+=w;
            q.push(v);
        }
    }
    ans=max(ans,res);
}

int main(){
//  freopen("a.in","r",stdin);
    rd(n);
    rep(i,1,n){
        int v,w;rd(v),rd(w);
        adde(i,v,w);
        deg[v]++;
    }
    rep(i,1,n)
        if(deg[i]==0)
            q.push(i);
    topo_sort();
    rep(i,1,n)
        if(deg[i]){
            q.push(i);
            get_ring();
        }
    printf("%d\n",ans);
    return 0;
}

E.最大差

水はまた問題であり、30秒を切断しました

ちょうどそれのようにそれを再度掃引

言っても過言ではありません

原因jへのチー赤ちゃんの水問題は、>私は、その前に各番号jのために、最小値は一定であります!我々はそれがミネソタ州保管だから、常に更新さans=max(ans,x-minn)O(n)の権利ことができ

const int N=1e6+10;
int n,minn=INT_MAX,ans;

int main(){
    rd(n);
    rep(i,1,n){
        int x;rd(x);
        minn=min(minn,x);
        ans=max(ans,x-minn); 
    }
    printf("%d",ans);
    return 0;
}

F.乱数ジェネレータを[秋を知るためではありません]

- 数学

int work(int x)
{
    if(x==1)return 0;
    else return work(rand(1,x))+1;
}

Q \(\テキスト{ワーク() } \) 数が戻り値が期待されます

正のソリューションは、(ああ、Baiduのをカウントすることはできません)オイラーの定数$ \ガンマ= 0.5772156649015328 ... $を使用しています

そのような式

\(1+ \ FRAC {1} {2} + \ FRAC {1}、{3} + ... + \ FRAC {1} {N} = \ LN N + \ガンマ\)

この関係は、それが少しある可能性があり......

#include <cstdio>
#include <cmath>
using namespace std;
double a=1,s=1;
const double ola=0.5772156649015328;
int n,i;
int main()
{
    scanf("%d",&n);
    if(n==1){printf("%.5f\n",0);return 0;}
    if (n<=1000000)
    for(i=2;i<=n;i++)
    {
        a=(double)s/(i-1)+1;
        s+=a;
    }
    else
    a=log(n-1)+1+ola;
    printf("%.5f\n",a);
    return 0;
}

G.サイクル

- ホーナー法、組み合わせの数

このサイクル

for(a[1]=1;a[1]<=n;a[1]++)
    for(a[2]=1;a[2]<=a[1];a[2]++)
        for(a[3]=1;a[3]<=a[2];a[3]++)
        for(a[k]=1;a[k]<=a[k-1];a[k]++)

ただ、いくつかの無知を参照し始め、その後、その非常に単純なを見つけました

k層をKに相当するサイクル数から選択され

したがって総数から選択された番組の数に相当するサイクル数n K、すなわち、C(n、k)は

const int N=500010,mod=1e9+7;
int n,m,k,q;
int a[N],fac[N];

inline int f(int x){
    int res=0;
    dwn(i,m,0)
        res=(res*x%mod+a[i])%mod;
    return res;
}

inline int ksm(int a,int k,int mod){
    k%=mod;
    int res=1;
    for(;k;k>>=1){
        if(k&1)res=1ll*res*a%mod;
        a=1ll*a*a%mod;
    }
    return res;
}

inline int inv(int x){return ksm(x,mod-2,mod);}

inline int get_tot(){
    fac[0]=1;
    rep(i,1,n)
        fac[i]=fac[i-1]*i%mod;
    return fac[n]*inv(fac[n-k])%mod*inv(fac[k])%mod;
}

#undef int
int main(){
#define int long long
    rd(n),rd(m),rd(k),rd(q);
    q%=mod;//不加这句会WA两个点 
    rep(i,0,m)rd(a[i]);
    int tot=get_tot();
    printf("%lld",1LL*f(q)*tot%mod);
    return 0;
}
/*
10 3 3 2
1 3 3 1
*/
//3240

H.席会議

オンデマンド逆の順序で--map +マージソート

教師の不満の一つのペアだけのオリジナルが正のシーケンスである場合は、元の順序と順序が異なる場合には、質問の本来の意味となり、今では逆の場合:逆に番号を見つけます

const int N=1e5+10;
int a[N],tmp[N];
map<string,int>mp;
string s;
int n,ans=0;

inline void merge_sort(int l,int r){
    if(l>=r)return ;
    int mid=(l+r)>>1;
    merge_sort(l,mid);
    merge_sort(mid+1,r);
    int i=l,j=mid+1,k=l;
    while(i<=mid && j<=r){
        if(a[i]<=a[j])
            tmp[k++]=a[i++];
        else{
            tmp[k++]=a[j++];
            ans+=mid-i+1;
        }
    }
    while(i<=mid)
        tmp[k++]=a[i++];
    while(j<=r)
        tmp[k++]=a[j++];
    rep(i,l,r)a[i]=tmp[i];
}

#undef int
int main(){
#define int long long
    rd(n);
    rep(i,1,n){
        cin>>s;
        mp[s]=i;
    }
    rep(i,1,n){
        cin>>s;
        a[i]=mp[s]; 
    }
    merge_sort(1,n);
    printf("%lld\n",ans);
    return 0;
}

I.の誕生日の贈り物

- プライム関連

素数の問題の性質をよく理解

ソーLCM(a、b)は== nは偶然の一致!
n個の素数分解のために、\(N ^ {C1} = P1 + P2 + P3 ^ ^ {C2}、{C3} + ... + PN CN ^ {}は\)各素数PIのために、持っている(\ maxは(ci_a、ci_b)= CI; \)

開始考察:次いでci_a == CI、CI + 1方法を選択された化合物を有していてBが(また、0カウント)同様に、ci_b == CI、CI + 1は、選択されたメソッドの化合物が存在する場合。

2CI + 2種類まで追加し、このような状況ci_a == ci_b == ciは、その後、側面を忘れてしまったとき-1ごとに、素数持って、2*c[i]+1乗算原理を乗算し、種を

Nは、ケース自体が大きな素数であることを忘れないでください

#include<bits/stdc++.h>
using namespace std;
const int N=10000010;
typedef long long ll;
ll n,ans=1;
int tot;
bool flag[N];
int prim[N];
void prime()
{
    for(int i=2;i<=N;i++)
    {
        if(!flag[i]) prim[++tot]=i;
        for(int j=1;j<=tot;j++)
        {
            if(i*prim[j]>N-1) break;
            flag[i*prim[j]]=1;
            if(i%prim[j]==0) break;
        }
    }
}
ll part(ll x)
{
    for(int i=1;i<=tot;i++) 
    {
        int t=1;
        if(prim[i]*prim[i]>n) break;
        while(x%prim[i]==0) x/=prim[i],t++;
        if(t>1) ans*=(2*t-1);
    }
    if(x>1) ans*=(2*(1+1)-1);
    return ans;
}
int main()
{
    prime();
    scanf("%lld",&n);
    printf("%lld",part(n));
    return 0;
}

彼の子供を持つJ. HKE

- リングを求めて

この問題は、情報及びP2661の送信に幾分類似しているが、この問題はまた、リングを必要とされます

私たちは開始点に達することができる場合は、各ポイントのために、我々はパス形式リングは、リングのサイズが長いリング徒歩整数倍の大きさは行かないと等価であるとと言うことですつまり、サイクルであること、その後、行くために指定されたルートをたどります。

これによると、我々は決定されているリングのすべてを入れて、その後、座席番号kの大きさを変えることができる位置は、各チャイルドシートの変更を求めることができるように、リングを法。Oの複雑さ(NK)

\(\テキスト{PS} \ ) 同じリング上のポイントに、私たちが訪問したラベルを指示することができ、再びリングを探す必要はありませんサイトを訪問しました

const int N=1e6+10;
int n,k;
int to[N],vis[N],ring[N],new_pos[N],ans[N];

inline void get_ring(int st){
    int p=st,size=0;
    do{
        p=to[p];
        vis[p]=1;
        ring[++size]=p;
    }while(p!=st);
    int t=k%size;
    rep(i,1,size)
        new_pos[ring[i]]=ring[(i+t-1)%size+1];//防止数组下标为0
}

int main(){
    rd(n),rd(k);
    rep(i,1,n)rd(to[i]);
    rep(i,1,n)
        if(!vis[i])
            get_ring(i);
    rep(i,1,n)ans[new_pos[i]]=i;
    rep(i,1,n)
        printf("%d ",ans[i]);
    return 0;
}

私が知っている[秋] K.宝物を取得できませんでした

質問は、私は、標準的なプロセスに直接......木の二次元配列のような2次元マトリックスを達しないだろう

#include<cstdio>
const int maxn=2501;
typedef int bit[maxn][maxn];
int n,m,x1,y1,x2,y2,k,ch,a,b,tmp,ans,t;
bit pre,ipre,jpre,ijpre;
char ins[3];
void read(int&x)
{
    x=0,ch=getchar();
    while(ch>'9'||ch<'0')ch=getchar();
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
}
void modify(bit&s,int x,int y,int val)
{
    for(register int i=x;i<=n;i+=i&-i)
        for(register int j=y;j<=n;j+=j&-j)
            s[i][j]^=val;
}
int query(bit&s,int x,int y)
{
    int ans=0;
    for(register int i=x;i;i-=i&-i)for(register int j=y;j;j-=j&-j)ans^=s[i][j];
    return ans;
}
int Ask(int x2,int y2)
{
    int t=0;
    if(x2*y2&1)t^=query(pre,x2,y2);
    if(x2&1)t^=query(jpre,x2,y2);
    if(y2&1)t^=query(ipre,x2,y2);
    return t^query(ijpre,x2,y2);
}
void Change(int i,int j,int val)
{
    modify(pre,i,j,val);
    if((j-1)&1)modify(jpre,i,j,val);
    if((i-1)&1)modify(ipre,i,j,val);
    if((j-1)*(i-1)&1)modify(ijpre,i,j,val);
}
int Query(int x1,int y1,int x2,int y2){return Ask(x2,y2)^Ask(x1-1,y2)^Ask(x2,y1-1)^Ask(x1-1,y1-1);}
void Modify(int x1,int y1,int x2,int y2,int val){Change(x1,y1,val),Change(x2+1,y1,val),Change(x1,y2+1,val),Change(x2+1,y2+1,val);}
int main()
{
    read(n),read(m);
    while(m--)
    {
        scanf("%s",ins);read(x1),read(y1),read(x2),read(y2);
        if(ins[0]=='Q')
        {
            ans=Query(x1,y1,x2,y2);
            for(register int i=0;i<30;++i)putchar(ans&(1<<i)?'2':'1');
            puts("");
        }
        else
        {
            read(k);t=0;
            while(k--)read(a),read(b),t^=((b&1)<<(a-1));
            if(t)Modify(x1,y1,x2,y2,t);
        }
    }
    return 0;
}

[L.]秋の簡単な機能を知るために取得していません

- ???

法律審査をf(n)を探していたとき、気持ちが法律2,4,2,3,2,3,2,3,2,3,2,3に従って起こるが、後に登場しなければなりませんない同じ番号......その後、場所の故障法則のトラブルシューティングを続行する他の違いがありますいくつかのポジションを見つけた唯一の愚か者は50pt後に除外短い最後に......法律を弱体化させる......

正のソリューションは、ああ理解していない......

#include<cstdio>
typedef long long ll;
ll pre[55],m,cnt;
const ll mod=1e9+7;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
ll qpow(ll a,ll n)
{
    ll res=1;
    for(;n;(a*=a)%=mod,n>>=1)if(n&1)(res*=a)%=mod;
    return res;
}
int main()
{
    pre[1]=1;
    for(register int i=2;i<=50;++i)pre[i]=lcm(pre[i-1],i);
    scanf("%lld",&m);
    for(register int i=3;i<=50;i+=2)cnt+=m/pre[i-1]-m/pre[i];
    printf("%lld\n",qpow(2,(m-1)>>1)*qpow(3,cnt-1)%mod*qpow(4,(m>>1)-cnt)%mod);
    return 0;
}

M.列ゲーム

- 間隔DP

そして真ん中の2つの数のすべての数値が排除されている場合だけ我々2つの数値を選択する必要はありませんが、排除する互いに素であります

F [I] [J] F [ I ] [ J ]セクションの数の最大数は、我々が最も重要な答えはF [1]で取得するので、逃げることです後、[I、J]を示す[N-] F [1] [ N-

最後に、注目すべきオープン\ {テキスト長い長い}長い長いこと!(開いていない後は、オープンゼロバースト\ {テキスト} AC AC)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=810;
int n;
ll a[N],s[N],b[N],sum;
ll f[N][N];
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&b[i]),s[i]=s[i-1]+b[i];
        if(i>1&&gcd(a[i-1],a[i])!=1) f[i-1][i]=b[i-1]+b[i];
    }
    for(int len=3;len<=n;len++)//区间长度
        for(int i=1;i<=n-len+1;i++)//左端点
        {
            int j=i+len-1;//右端点
            for(int k=i;k<j;k++) f[i][j]=max(f[i][j],f[i][k]+f[k+1][j]);//更新区间最大值
            if(f[i+1][j-1]==s[j-1]-s[i])//说明[i+1,j-1]已经全部被取走,这样j,i才能碰到
                f[i][j]=max(f[i][j],f[i+1][j-1]+(gcd(a[i],a[j])==1?0:(b[i]+b[j])));
            else f[i][j]=max(f[i][j],f[i+1][j-1]);//否则直接转移子区间的值
        }
    printf("%lld",f[1][n]);
    return 0;
}

より好ましくは、方法(高速標準プロセスより実行):(から実証:\テキストを{lwz dalao} lwz dalao)

最初の全て予め決め間隔合法性を除去し、次いで線形DPに応じて転送

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=810;
int n;
ll a[N],b[N],s[N];
ll f[N][2];//f[i][0/1]表示前i个数中i位置的数不删/删得到的最大值
bool vis[N][N];//vis[i][j]=1表示[i,j]可以全部被取走
ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) 
    {
        scanf("%lld",&a[i]);
        if(i>1&&gcd(a[i-1],a[i])!=1) vis[i-1][i]=1;
    }
    for(int i=1;i<=n;i++) scanf("%lld",&b[i]),s[i]=s[i-1]+b[i];
    for(int len=4;len<=n;len+=2)
        for(int i=1;i<=n-len+1;i++)
        {
            int j=i+len-1;
            if(vis[i+1][j-1]&&gcd(a[i],a[j])!=1) {vis[i][j]=1;continue;}
            for(int k=i+1;k<j-1;k++)
                if(vis[i+1][k]&&vis[k+1][j-1]&&gcd(a[i],a[j])!=1)
                    {vis[i][j]=1;break;}
        }
    for(int i=2;i<=n;i++)
        for(int j=1;j<i;j++)
        {
            f[i][0]=max(f[i][0],max(f[j][0],f[j][1]));
            if(vis[j][i]) f[i][1]=max(f[i][1],f[j][0]+b[j]+b[i]+s[i-1]-s[j]);
        }
    printf("%lld",max(f[n][0],f[n][1]));
    return 0;
}

追伸:これは最後の大きなフロントNOIp2018ですACMシミュレーションゲーム、と彼らは彼の基本アルゴリズムを統合の最終日に、一部またはいくつかの欠如を来て、NOIp2018の再戦での成功を達成するために努力することができますことを感じます!

1スリランカにおける機械の成否は、急襲を落ちました!

P1471の分散(質問の兄)

しかし、また、(私自身、何度も何度もオーバーどのように更新する)に加えて、操作の範囲を維持するために、

しかし、ポイントのほとんどのガチョウのピットは、この数kに追加されている实数魏・チューン非常に長い時間!

主に更新(INT 0、int型のx、 int型のy、int型K)
INT kの二重Kああに書き込む私は赤ちゃんの知恵でした。

その後、彼は見るためにタイトルに書いた实数ように注意してくださいときLiangziの子供を!

#include<bits/stdc++.h>
using namespace std;
template <typename T>inline void rd(T &x){x=0;char c=getchar();int f=0;while(!isdigit(c)){f|=c=='-';c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}x=f?-x:x;} 
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define dwn(i,a,b) for(int i=a;i>=b;--i)
#define mem(a,b) memset(a,b,sizeof(a))
#define ee(i,u) for(int i=head[u];i;i=e[i].next)

#define lson o<<1
#define rson o<<1|1
const int N=100010;

struct tree{
    int l,r;
    double sum,ssum,tag_add;
}t[N<<2];

double val[N];
int n,m;

inline void pushup(int o){
    t[o].sum=(t[lson].sum+t[rson].sum);
    t[o].ssum=(t[lson].ssum+t[rson].ssum);
}

inline void f(double delta,int o){
    int l=t[o].l,r=t[o].r;
    t[o].tag_add+=delta;
    t[o].ssum=t[o].ssum+2*delta*t[o].sum+delta*delta*(r-l+1);
    t[o].sum+=delta*(r-l+1);
} 

inline void pushdown(int o){
    if(t[o].tag_add){
        f(t[o].tag_add,lson);
        f(t[o].tag_add,rson);
        t[o].tag_add=0;
    }
}

inline void build(int o,int l,int r){
    t[o].tag_add=0;
    t[o].l=l,t[o].r=r;
    if(l==r){
        t[o].sum=val[l];
        t[o].ssum=val[l]*val[l];
        return ;
    }
    int mid=(l+r)>>1;
    build(lson,l,mid);
    build(rson,mid+1,r);
    pushup(o);
}

inline void update(int o,int x,int y,double k){
    int l=t[o].l,r=t[o].r;
    if(x<=l && r<=y){
        f(k,o);
        return ;
    }
    pushdown(o);
    int mid=(l+r)>>1;
    if(x<=mid)update(lson,x,y,k);
    if(mid<y)update(rson,x,y,k);
    pushup(o);
} 

inline double query_sum(int o,int x,int y){
    int l=t[o].l,r=t[o].r;
    if(x<=l && r<=y){
        return t[o].sum;
    }
    pushdown(o);
    double res=0;
    int mid=(l+r)>>1;
    if(x<=mid)res=(res+query_sum(lson,x,y));
    if(mid<y)res=(res+query_sum(rson,x,y));
    return res;
}

inline double query_ssum(int o,int x,int y){
    int l=t[o].l,r=t[o].r;
    if(x<=l && r<=y){
        return t[o].ssum;
    }
    pushdown(o);
    double res=0;
    int mid=(l+r)>>1;
    if(x<=mid)res=(res+query_ssum(lson,x,y));
    if(mid<y)res=(res+query_ssum(rson,x,y));
    return res;
}

int main(){
    #ifdef WIN32
    freopen("fangcha.txt","r",stdin);
    #endif
    rd(n),rd(m);
    rep(i,1,n)scanf("%lf",&val[i]);
    build(1,1,n);
    while(m--){
        int op,x,y;
        double k;
        rd(op);
        if(op==1){
            rd(x),rd(y);scanf("%lf",&k);
            update(1,x,y,k);
        }
        else if(op==2){
            rd(x),rd(y);
            double ans=query_sum(1,x,y)/(y-x+1);
            printf("%.4lf\n",ans); 
        }
        else if(op==3){
            rd(x),rd(y);
            double sum1=query_ssum(1,x,y)/(y-x+1);
            double sum2=query_sum(1,x,y)/(y-x+1);
            printf("%.4lf\n",sum1-sum2*sum2);
        }
    }
    return 0;
}

P2434 [SDOI2005]間隔(合成部モデル)

  • 左点に応じて小から大順に各間隔について
  • 各間隔を列挙する。
    • R <鳴っ[I] .Lは、現在の間隔(L、R)を出力する場合、更新はl=rang[i].l,r=rang[i].r;次のインターバル条件が満たされたシークし続けます。
    • 他の説明と2つの間隔を持って、更新r=max(r,range[i].r)実際に左のエンドポイントは、(更新することはできませんl=min(l,range[i].l)、すべての後、左点列まあに従ってことが予定されている、ので、
  • 最後に、出力L、Rを忘れないでください

弟の質問にP2082間隔カバレッジ(強化版)

長さJiuhaolaについての更新は、そのハードではない、時間の限定範囲を見つけます

算術配列式をプッシュするP5077 Tweetuzki愛

開いていないlong long父親を見て

ハンドプッシュ柿、逆列挙、検索出口(これはA1の最小を見つけることを保証することができます)。

おすすめ

転載: www.cnblogs.com/sjsjsj-minus-Si/p/11845572.html