LOJ576 "LibreOJ NOIラウンド#2" ゲームの出席

被験体
形質転換を行う:
各コスト\(\ GCD \ limits_ {iは = L + 1} ^ rB_i \) コストは、接続することができる((L、R)\ \ ) これはエッジです。
その後、我々は要求\(0 \ SIMのn \)最小スパニングツリーを。
クラスカルの考え方によると、\((0、N-)\) このエッジが選択されます。
その後、プリムとの考え方によると、いくつかのポイントのために、私たちはその最短辺を確認する必要があります。
一方、明らかに\(I \) 最短の辺である\((I、0)\ ) または\(\)(I、N-) 右側は、(L_iを= \ GCD \ limits_ \ {J = 1} ^ iB_j \) と\(R_iを= \ GCD \ limits_ {J} ^ = I + nB_j。1 \)
明らかに\(L_iを\)単調増加ではありません(R_iと\)\非減少です。
したがって、\ \ FORALL I \ [0、P(\ N- [0、で\ PをEXISTS)、R_iを\ルL_iを、\ FORALL I \で(P、N - )、L_iを\ルR_iを\)
我々は、セグメントツリーを用いて、各セクションを維持することができる([L、R] \ \ )\(\ GCD \ limits_ = {I}。1 + L ^ rB_i \) 次いで線分は、バイナリツリー決定\(P \)を
一点の変形の対象を直接変更してもよいです。
残りは求めている({0} + ^ pR_i \ SUM \私は= limits_ {P ^ {+}。1. 1-N- L_iを} \ = I limits_ \ SUMを\)\
考慮(L_iを\)は\\(R_iを\)数がの値である\(ログ\ n \)レベル、我々は、これらの激しいツリー線分とそれに対応する値の範囲を特定することができます。

#include<cstdio>
#include<cctype>
#define ls p<<1
#define rs p<<1|1
#define mid ((l+r)>>1)
#define ll long long
namespace IO
{
    char ibuf[(1<<21)+1],obuf[(1<<21)+1],stk[19],*iS,*iT,*oS=obuf,*oT=obuf+(1<<21);
    char Get(){return (iS==iT? (iT=(iS=ibuf)+fread(ibuf,1,(1<<21)+1,stdin),(iS==iT? EOF:*iS++)):*iS++);}
    void Flush(){fwrite(obuf,1,oS-obuf,stdout),oS=obuf;}
    void Put(char x){*oS++=x;if(oS==oT)Flush();}
    int read(){int x=0,c=Get();while(!isdigit(c))c=Get();while(isdigit(c))x=x*10+c-48,c=Get();return x;}
    void write(ll x){int top=0;while(x)stk[++top]=(x%10)+48,x/=10;while(top)Put(stk[top--]);Put('\n');}
}
using namespace IO;
int gcd(int n,int m){return !m||!n? n+m:gcd(m,n%m);}
int t[400007];
void build(int p,int l,int r)
{
    if(l==r) return (void)(t[p]=read());
    build(ls,l,mid),build(rs,mid+1,r),t[p]=gcd(t[ls],t[rs]);
}
void update(int p,int l,int r,int x,int v)
{
    if(l==r) return (void)(t[p]=v);
    x<=mid? update(ls,l,mid,x,v):update(rs,mid+1,r,x,v);t[p]=gcd(t[ls],t[rs]);
}
int Find(int p,int l,int r,int a,int b)
{
    if(l==r) return l;
    int x=gcd(a,t[ls]),y=gcd(b,t[rs]);
    return x<=y? Find(ls,l,mid,a,y):Find(rs,mid+1,r,x,b);
}
ll cal1(int p,int l,int r,int x,int v)
{
    if(l==r) return gcd(t[p],v);
    int a=gcd(t[rs],v),b=gcd(t[ls],a);
    return x<=mid? cal1(ls,l,mid,x,a):(a==b? 1ll*(mid-l+1)*a:cal1(ls,l,mid,x,a))+cal1(rs,mid+1,r,x,v);
}
ll cal2(int p,int l,int r,int x,int v)
{
    if(l==r) return gcd(t[p],v);
    int a=gcd(t[ls],v),b=gcd(t[rs],a);
    return x>mid? cal2(rs,mid+1,r,x,a):(a==b? 1ll*(r-mid)*a:cal2(rs,mid+1,r,x,a))+cal2(ls,l,mid,x,v);
}
int main()
{
    int n=read(),Q=read();
    build(1,1,n);
    for(int p,v;Q;--Q) p=read(),v=read(),update(1,1,n,p,v),p=Find(1,1,n,0,0),write(cal1(1,1,n,p,0)+cal2(1,1,n,p,0)-t[1]);
    return Flush(),0;
}

おすすめ

転載: www.cnblogs.com/cjoierShiina-Mashiro/p/11888369.html