区間開方、区間求和、線分ツリー
2460 ワード
普通の問題2
Time Limit: 500 MS Memory Limit: 64 MB
Submit Status
長さnの数列a 1...anとnの操作を与え,操作は区間開方,区間求和に関連する.
Input
1行目にn(1≦n≦50000)の数字を入力します.
2行目はn個の非負の整数を入力し、i番目の数字はai、(0≦ai≦109)はスペースで区切られる.
次にn行の質問を入力し、各行に4つの数字opt,l,r,cを入力し、スペースで区切ります.
opt=0であれば、[l,r]の間に位置する数字がすべて開方されることを示す.区間の各ai(l≦i≦r)について、ai→⌊√ai⌋
opt=1の場合、[l,r]にあるすべての数字の和を表す.
Output
質問のたびに、z行の数値を出力して答えを表します.
すべてのデータが
Sample input and output
Sample Input
Sample Output
実はこの問題はブロックで作ることができて、詳しくは私のブログを見て、構想とブロックの差は多くなくて、0あるいは1に出会って0(更に開方値は変わらない)とマークして、その他のマークは1で、
1つの区間が0と表記されている場合は、開方しません.そうしないと、暴力的にサブ区間を検索します.
Time Limit: 500 MS Memory Limit: 64 MB
Submit Status
長さnの数列a 1...anとnの操作を与え,操作は区間開方,区間求和に関連する.
Input
1行目にn(1≦n≦50000)の数字を入力します.
2行目はn個の非負の整数を入力し、i番目の数字はai、(0≦ai≦109)はスペースで区切られる.
次にn行の質問を入力し、各行に4つの数字opt,l,r,cを入力し、スペースで区切ります.
opt=0であれば、[l,r]の間に位置する数字がすべて開方されることを示す.区間の各ai(l≦i≦r)について、ai→⌊√ai⌋
opt=1の場合、[l,r]にあるすべての数字の和を表す.
Output
質問のたびに、z行の数値を出力して答えを表します.
すべてのデータが
int
の範囲内であることを保証します.Sample input and output
Sample Input
Sample Output
4
1 2 2 3
0 1 3 1
1 1 4 4
0 1 2 2
1 1 2 4
6
2
実はこの問題はブロックで作ることができて、詳しくは私のブログを見て、構想とブロックの差は多くなくて、0あるいは1に出会って0(更に開方値は変わらない)とマークして、その他のマークは1で、
1つの区間が0と表記されている場合は、開方しません.そうしないと、暴力的にサブ区間を検索します.
#include
#include
#include
using namespace std;
const int maxn=50005;
struct node
{
int tag;
int val;
}b[maxn<<2];
int a[maxn];
void judge(int rt)
{
if(b[rt].val==0||b[rt].val==1) b[rt].tag=0;
else b[rt].tag=1;
}
void build(int l,int r,int rt)
{
if(l==r)
{
b[rt].val=a[l];
if(b[rt].val==0||b[rt].val==1) b[rt].tag=0;
else b[rt].tag=1;
return ;
}
int mid=(l+r)>>1;
build(l,mid,rt*2);
build(mid+1,r,rt*2+1);
b[rt].val=b[rt*2].val+b[rt*2+1].val;
b[rt].tag=b[rt*2].tag||b[rt*2+1].tag;
}
int query(int l,int r,int rt,int ll,int rr)
{
if(ll<=l&&r<=rr)
{
return b[rt].val;
}
int mid=(l+r)>>1;
int ans=0;
if(ll<=mid) ans+=query(l,mid,rt*2,ll,rr);
if(rr>mid) ans+=query(mid+1,r,rt*2+1,ll,rr);
return ans;
}
void change(int l,int r,int rt,int ll,int rr)
{
if(ll<=l&&r<=rr&&!b[rt].tag) return ;
if(l==r)
{
b[rt].val=int(sqrt(b[rt].val));
judge(rt);
return ;
}
int mid=(l+r)>>1;
if(ll<=mid) change(l,mid,rt*2,ll,rr);
if(rr>mid) change(mid+1,r,rt*2+1,ll,rr);
b[rt].val=b[rt*2].val+b[rt*2+1].val;
b[rt].tag=b[rt*2].tag||b[rt*2+1].tag;
}
int main()
{
int n;
int o,l,r,c;
while(scanf("%d",&n)!=EOF)
{
for(int i=1;i<=n;++i)
scanf("%d",&a[i]);
build(1,n,1);
for(int i=0;i