⑨数学の天才と等差数列
:長さNのシーケンスは、次の2つの操作をサポートする必要性を考えます
- 修正のシングルポイント
- 呼び掛けゾーン内・かどうか算術シーケンス番号各昇順
N≤100000、M≤200000、データiは ≦10 9
問題の解決策
等差級数にセクション数は、明らかに間隔の中で最も値が必要かどうかを知ることができるようにするために(すなわち、最初の列に、最後にエントリの数)を計算公差に対応します。
算術級数間隔にノートの数ができる場合は、以下を満たす必要があります:
- ゼロトレランス;
- 公差は、非同一素子内の列の数、隣接差分値GCDの公差ゼロではありません。
したがって、メンテナンスが必要とされる、最小間隔最大値、同一の前駆体に分別カラムGCD間隔、数及び各要素の位置との差。各要素は、前駆体ロケーション・セットの同じ数を設定することが可能で維持します。
あなたは間違っているだろうか?
メンテナンス間隔の最大値、最小値、及び、二乗和は、その後、判断します。
ライン上に立ち上げた等差数列広場や数式暴力。
一部の人々は、カードを交換することができると言いますか?
typedef __int128 LL;
CO int N=300000+10;
struct node{
int min,max;
LL sum1,sum2;
};
node operator+(CO node&a,CO node&b){
return (node){
min(a.min,b.min),max(a.max,b.max),
a.sum1+b.sum1,a.sum2+b.sum2
};
}
node tree[4*N];
#define lc (x<<1)
#define rc (x<<1|1)
void build(int x,int l,int r){
if(l==r){
int v=read<int>();
tree[x]=(node){v,v,v,(LL)v*v};
return;
}
int mid=(l+r)>>1;
build(lc,l,mid),build(rc,mid+1,r);
tree[x]=tree[lc]+tree[rc];
}
void change(int x,int l,int r,int p,int v){
if(l==r){
tree[x]=(node){v,v,v,(LL)v*v};
return;
}
int mid=(l+r)>>1;
if(p<=mid) change(lc,l,mid,p,v);
else change(rc,mid+1,r,p,v);
tree[x]=tree[lc]+tree[rc];
}
node query(int x,int l,int r,int ql,int qr){
if(ql<=l and r<=qr) return tree[x];
int mid=(l+r)>>1;
if(qr<=mid) return query(lc,l,mid,ql,qr);
if(ql>mid) return query(rc,mid+1,r,ql,qr);
return query(lc,l,mid,ql,qr)+query(rc,mid+1,r,ql,qr);
}
int main(){
int n=read<int>(),m=read<int>();
build(1,1,n);
int yes=0;
while(m--){
if(read<int>()==1){
int p=read<int>()^yes,v=read<int>()^yes;
change(1,1,n,p,v);
}
else{
int l=read<int>()^yes,r=read<int>()^yes,k=read<int>()^yes;
bool valid=1;
node x=query(1,1,n,l,r);
if(x.max-x.min!=(LL)(r-l)*k) valid=0;
if(x.sum1!=(LL)(x.min+x.max)*(r-l+1)/2) valid=0;
if(x.sum2!=(LL)(r-l+1)*x.min*x.min+(LL)2*k*(r-l)*(r-l+1)/2*x.min
+(LL)k*k*(r-l)*(r-l+1)*(2*r-2*l+1)/6) valid=0;
puts(valid?"Yes":"No"),yes+=valid;
}
}
return 0;
}
間隔GCD 4302 0x40の「データ構造の詳細設定」の例
説明
長さN A、及びM命令(N≤5* 10 ^ 5、Mの一連の所与の <= ^ 5〜10)、 各命令は、以下のいずれであってもよい:
"C LRD"、Aは示し[L]、A [L + 1]、...、A [R]はプラスDです。
"QのLR"、問い合わせAを示す[L]、A [L + 1]、...、A [R] 最大公約数(GCD)。
入力形式
被験者に記載されているように、各命令フォーマットの次の行に示すように、2つの整数N、Mの最初の行、N 2行目あい、Mは整数です。
出力フォーマット
各お問い合わせについては、出力整数の答え。
サンプル入力
5 5 1 3 5 7 9 Q 1 5 C 1 5 1 Q 1 5 C 3 3 6 Q 2 4
サンプル出力
1 2 4
データ範囲と表記
- Nは、M≤2* 10 ^ 5、L <= R、データの数は、任意の時間シーケンスがないより62-1 ^ 2以上の正の整数であることを保証します。
分析
"減少技術"、\は(GCDは、(Xは、Yは、Z)は= GCD(X、YX、ZY)\) 、そう
gcd_ {I = L \ [\ GCD \} ^ R A [L] =( [L]、\ gcd_ {
I = L + 1} ^ R([I] -A [I-1]))\] したがって、差分配列セグメントツリーGCD、線分ツリー変更部の一点を維持するためにクエリ、新しい配列を維持するために、ツリー差分配列と元のシングルポイントクエリー配列の間隔の値を変更します。
時間複雑\(O(M \ログN )\)
co int N=5e5+1;
int n,m;
ll a[N],b[N],c[N];
#define lowbit(i) (i&-i)
void add(int p,ll v){
for(;p<=n;p+=lowbit(p)) c[p]+=v;
}
ll ask(int p){
ll re=0;
for(;p;p-=lowbit(p)) re+=c[p];
return re;
}
ll s[N*4];
ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
#define lc (x<<1)
#define rc (x<<1|1)
void build(int x,int l,int r){
if(l==r) return s[x]=b[l],void();
int mid=l+r>>1;
build(lc,l,mid),build(rc,mid+1,r);
s[x]=gcd(s[lc],s[rc]);
}
void change(int x,int l,int r,int p){
if(l==r) return s[x]=b[l],void();
int mid=l+r>>1;
if(p<=mid) change(lc,l,mid,p);
else change(rc,mid+1,r,p);
s[x]=gcd(s[lc],s[rc]);
}
ll query(int x,int l,int r,int ql,int qr){
if(ql>qr) return 0;
if(ql<=l&&r<=qr) return s[x];
int mid=l+r>>1;
if(qr<=mid) return query(lc,l,mid,ql,qr);
if(ql>mid) return query(rc,mid+1,r,ql,qr);
return gcd(query(lc,l,mid,ql,qr),query(rc,mid+1,r,ql,qr));
}
int main(){
// freopen("CH4302.in","r",stdin),freopen("CH4302.out","w",stdout);
read(n),read(m);
for(int i=1;i<=n;++i) b[i]=read(a[i])-a[i-1];
build(1,1,n); // edit 1: reserve for changing b[1]
for(int l,r;m--;){
static char op[2];
scanf("%s",op),read(l),read(r);
if(op[0]=='C'){
ll d=read<ll>(); // edit 2
b[l]+=d,change(1,1,n,l),add(l,d);
if(r+1<=n) b[r+1]-=d,change(1,1,n,r+1),add(r+1,-d);
}
else printf("%lld\n",llabs(gcd(a[l]+ask(l),query(1,1,n,l+1,r))));
}
return 0;
}