LibreOj 6281数列ブロック入門5区間開方+区間和
29761 ワード
数列ブロック入門4
リンク:LibreOj 6281
タイトルの説明
長さnの数列とnの操作を与え,操作は区間開方,区間求和に関連する.
入力フォーマット
1行目にnという数字を入力します.
2行目にはn個の数字を入力し、i番目の数字はa[i]で、スペースで区切ります.
次にn行の質問を入力し、各行に4つの数字op、l、r、cを入力してスペースで区切ります.
op=0の場合、[l,r]の間の数字をすべて開方する(sqrtは下に整列する)
op=1の場合、[l,r]のすべての数字の和を表す
出力フォーマット
質問のたびに、1行1つの数字を出力して答えを表します.
サンプル入力
4 1 2 2 3 0 1 3 1 1 1 4 4 0 1 2 2 1 1 2 4
サンプル出力
6 2
分析:
開方は操作が難しく、区間とsumについて、区間の各値が開方されている場合は、すべての値を1回加算しなければ区間とを更新できません.しかし、0ではない数字が何度も開くと必ず1になります.遍歴するときは1か0であれば直接スキップすると判断します.1と0は開方が変わらないからです.1つの配列markタグ区間がすべて0と1であるかどうかを開き、検索時に区間がすべて0と1であると判断すると、直接1つの区間をスキップすることができます.
マイコード:
リンク:LibreOj 6281
タイトルの説明
長さnの数列とnの操作を与え,操作は区間開方,区間求和に関連する.
入力フォーマット
1行目にnという数字を入力します.
2行目にはn個の数字を入力し、i番目の数字はa[i]で、スペースで区切ります.
次にn行の質問を入力し、各行に4つの数字op、l、r、cを入力してスペースで区切ります.
op=0の場合、[l,r]の間の数字をすべて開方する(sqrtは下に整列する)
op=1の場合、[l,r]のすべての数字の和を表す
出力フォーマット
質問のたびに、1行1つの数字を出力して答えを表します.
サンプル入力
4 1 2 2 3 0 1 3 1 1 1 4 4 0 1 2 2 1 1 2 4
サンプル出力
6 2
分析:
開方は操作が難しく、区間とsumについて、区間の各値が開方されている場合は、すべての値を1回加算しなければ区間とを更新できません.しかし、0ではない数字が何度も開くと必ず1になります.遍歴するときは1か0であれば直接スキップすると判断します.1と0は開方が変わらないからです.1つの配列markタグ区間がすべて0と1であるかどうかを開き、検索時に区間がすべて0と1であると判断すると、直接1つの区間をスキップすることができます.
マイコード:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
typedef long long ll;
const int inf=0x3f3f3f3f;
const int inn=0x80808080;
using namespace std;
const int maxm=5e4+5;
int l[maxm],r[maxm];
int a[maxm],sum[maxm];
int belong[maxm];
int mark[maxm];
int block,num;
int n;
void build(){
block=sqrt(n);
num=n/block;
if(n%block)num++;
for(int i=1;i<=num;i++){
l[i]=(i-1)*block+1;
r[i]=i*block;
sum[i]=0;
mark[i]=0;// mark
}
r[num]=n;
}
void pd(int x){
for(int i=l[x];i<=r[x];i++){
if(a[i]>1){
return ;
}
}
mark[x]=1;
}
void update(int x,int y){
if(belong[x]==belong[y]){
if(mark[belong[x]]){
return ;
}
for(int i=x;i<=y;i++){
if(a[i]<=1){
continue;
}
sum[belong[i]]-=a[i]-sqrt(a[i]);//
a[i]=sqrt(a[i]);
}
pd(belong[x]);// mark
return ;
}
for(int i=x;i<=r[belong[x]];i++){
if(a[i]<=1)continue;
sum[belong[i]]-=a[i]-sqrt(a[i]);
a[i]=sqrt(a[i]);
}
pd(belong[x]);
for(int i=l[belong[y]];i<=y;i++){
if(a[i]<=1)continue;
sum[belong[i]]-=a[i]-sqrt(a[i]);
a[i]=sqrt(a[i]);
}
pd(belong[y]);
for(int i=belong[x]+1;i<belong[y];i++){
if(mark[i])continue;
for(int j=l[i];j<=r[i];j++){
if(a[j]<=1)continue;
sum[belong[j]]-=a[j]-sqrt(a[j]);
a[j]=sqrt(a[j]);
}
pd(i);
}
}
int ffind(int x,int y){
int ans=0;
if(belong[x]==belong[y]){
for(int i=x;i<=y;i++){
ans+=a[i];
}
return ans;
}
for(int i=x;i<=r[belong[x]];i++){
ans+=a[i];
}
for(int i=l[belong[y]];i<=y;i++){
ans+=a[i];
}
for(int i=belong[x]+1;i<belong[y];i++){
ans+=sum[i];
}
return ans;
}
int main(){
scanf("%d",&n);
build();
for(int i=1;i<=n;i++){
belong[i]=(i-1)/block+1;
scanf("%d",&a[i]);
sum[belong[i]]+=a[i];
}
for(int i=1;i<=n;i++){
int d,x,y,c;
scanf("%d%d%d%d",&d,&x,&y,&c);
if(d==0){
update(x,y);
}else{
printf("%d
",ffind(x,y));
}
}
return 0;
}