LOJ576 "LibreOJ NOI Round # 2" game attendance

Subject
to a transformation performed:
each cost \ (\ gcd \ limits_ {i = l + 1} ^ rB_i \) cost, can be connected \ ((l, r) \ ) This is an edge.
Then we request \ (0 \ sim n \) the minimum spanning tree.
According to the idea of Kruskal, \ ((0, the n-) \) this edge will be selected.
According to the idea of Prim and then, for some point, we need to find out its shortest side.
While apparent to \ (I \) , which is the shortest side of the \ ((i, 0) \ ) or \ ((I, n-) \) . Right side is \ (L_i = \ gcd \ limits_ {j = 1} ^ iB_j \) and \ (R_i = \ GCD \ limits_ {J} ^ = I + nB_j. 1 \) .
Obviously \ (L_i \) is not monotonically increasing, \ (R_i \) is nondecreasing.
Therefore, \ (\ EXISTS P \ in [0, n-), \ FORALL I \ in [0, P], R_i \ Le L_i, \ FORALL I \ in (P, n-), L_i \ Le R_i \) .
We can maintain each section with a segment tree \ ([l, r] \ )The \ (\ GCD \ limits_ = {I}. 1 + L ^ rB_i \) , then the line segment determined binary tree \ (P \) .
Subject to the modification of the single point may be directly modified.
The rest is seeking \ (\ SUM \ limits_ I = {0} + ^ pR_i \ SUM \ limits_ I = {P ^ {+}. 1. 1-n-L_i} \) .
Considering \ (L_i \) and \ (R_i \) number is the value of \ (\ log n \) level, we can identify these violent tree line segment and its corresponding value range.

#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;
}

Guess you like

Origin www.cnblogs.com/cjoierShiina-Mashiro/p/11888369.html