關於用線段樹去紀錄區間的一個問題


codeforces contest671的C題。

#include<bits/stdc++.h>//對函數f(i,j):left。right表示的是i的取值范圍。此時j的取值為1-k,其中k>=minn[n]&&k<=maxn[n],且k(minn)=minn[n],k(maxn)=maxn[n]
typedef long long ll;
using namespace std;
ll tree[
200010<<2];
int minn[200010<<2];
int maxn[200010<<2];
int add[200010<<2];
void pushDown(int temp,int left,int mid,int right,int temps)
{
tree[temp
<<1]=1LL*temps*(mid-left+1);
tree[temp
<<1|1]=1LL*temps*(right-mid);
add[temp
<<1]=temps;
add[temp
<<1|1]=temps;
maxn[temp
<<1]=maxn[temp<<1|1]=minn[temp<<1]=minn[temp<<1|1]=temps;
add[temp]
=0;
}
void ad(int i,int j,int temp,int left,int right,int n)
{
if(temp<=minn[n])
return;
if(left>=i&&right<=j&&temp>=maxn[n])
{
tree[n]
=1LL*(right-left+1)*temp;
add[n]
=maxn[n]=minn[n]=temp;
return;
}
int mid=(left+right)/2;
if(add[n])
pushDown(n,left,mid,right,add[n]);
if(j<=mid)
ad(i,j,temp,left,mid,n
<<1);
else if(i>mid)
ad(i,j,temp,mid
+1,right,n<<1|1);
else
{
ad(i,mid,temp,left,mid,n
<<1);
ad(mid
+1,j,temp,mid+1,right,n<<1|1);
}
tree[n]
=tree[n<<1]+tree[n<<1|1];
maxn[n]
=max(maxn[n<<1],maxn[n<<1|1]);
minn[n]
=min(minn[n<<1],minn[n<<1|1]);
}
vector
<int>v;
int l[200010][2],r[200010][2];
ll ans[
200010];
void deel(int pos,int val)
{
if(l[val][0]>pos||l[val][0]==0)
{
l[val][
1]=l[val][0];
l[val][
0]=pos;
}
else if(l[val][1]>pos||l[val][1]==0)
l[val][
1]=pos;
if(r[val][0]<pos)
{
r[val][
1]=r[val][0];
r[val][
0]=pos;
}
else if(r[val][1]<pos)
r[val][
1]=pos;
}
int main()
{
int n;
cin
>>n;
int val;
for(int i=1; i<=n; i++)
{
scanf(
"%d",&val);
for(int j=1; j*j<=val; j++)
{
if(val%j==0)
{
deel(i,j);
if(j*j!=val)
deel(i,val
/j);
}
}
}
for(int i=1; i<=n; i++)
ad(i,i,i
-1,1,n,1);
for(int i=200001; i>0; i--)
{
if(l[i][0]!=r[i][0])
{
ad(
1,l[i][0],r[i][1]-1,1,n,1);//當i在1-l[i][0]之間是,j必須小於等於r[i][1]-1才能保證把所有結果等於i的區間都包含進去了
ad(l[i][0]+1,l[i][1],r[i][0]-1,1,n,1);//同理
if(l[i][1]!=n)
ad(l[i][
1]+1,n,n,1,n,1);//同理,此時有可能l[i][1]==n
}
//此時線段樹中存儲的是使結果大於等於i的區間數目
ans[i]=1LL*n*n-tree[1];//所以ans[i]存儲的是結果小於i的區間數目
}
ll fin
=0;
for(int i=1;i<=200000;i++)
fin
+=(ans[i+1]-ans[i])*i;
printf(
"%I64d\n",fin);
return 0;
}

 


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
  © 2014-2022 ITdaan.com