又是一次帕金森,多打等号WA6次——真的伤心啊。
这题的正解是线段树,应该还是比较好想的。
对于修改操作,对于给定的区间中的每一个节点做单点修改,将该节点的值变为sqrt(该节点的值),之后就是线段树的维护了。
这题真的比较水,线段树连延迟标记都没有用到。
附上AC代码:
#include <cstdio>
#include <cctype>
#include <cmath>
#define lt (k<<1)
#define rt (k<<1|1)
#define mid ((l+r)>>1)
using namespace std;
struct note{
long long w;
bool b;
}t[262145];
long long n,o,x,y,m;
void read(long long& a){
static char c=getchar();a=0;int f=1;
while (!isdigit(c)) {if (c=='-') f=-1;c=getchar();}
while (isdigit(c)) a=a*10+c-'0',c=getchar();
a*=f;return;
}
void build(int k,int l,int r){
if (l==r){
read(t[k].w);
if (t[k].w==1||!t[k].w) t[k].b=1;
return;
}
build(lt,l,mid),build(rt,mid+1,r);
t[k].w=t[lt].w+t[rt].w,t[k].b=t[lt].b&t[rt].b;
return;
}
void change(int k,int l,int r,int ql,int qr){
if (l>qr||r<ql||t[k].b) return;
if (l==r&&ql<=l&&r<=qr){
t[k].w=(long long)sqrt(t[k].w);
if (t[k].w==1||!t[k].w) t[k].b=1;
return;
}
change(lt,l,mid,ql,qr),change(rt,mid+1,r,ql,qr);
t[k].w=t[lt].w+t[rt].w,t[k].b=t[lt].b&t[rt].b;
return;
}
long long query(int k,int l,int r,int ql,int qr){
if (l>qr||r<ql) return 0;
if (ql<=l&&r<=qr) return t[k].w;
return query(lt,l,mid,ql,qr)+query(rt,mid+1,r,ql,qr);
}
void swap(long long& x,long long& y){
long long z=x;x=y;y=z;
}
int main(void){
read(n),build(1,1,n);
read(m);
while (m--){
read(o),read(x),read(y);
if (x>y) swap(x,y);
switch (o){
case 1:printf("%lld\n",query(1,1,n,x,y));break;
case 2:change(1,1,n,x,y);break;
}
}
return 0;
}
帕呀帕呀帕金森,手贱真的挡不住啊。
P.S:CODE[VS]的2492 上帝造题的七分钟2和这题的解题思路是一模一样的,因此我就在这里贴一下代码了,懒得再去重新打一篇博客了。
附上AC代码:
#include <cstdio>
#include <cmath>
#define lt (k<<1)
#define rt ((k<<1)+1)
#define mid ((l+r)>>1)
using namespace std;
long long t[300010],n,o,x,y,m,ti;
void build(int k,int l,int r){
if (l==r){
scanf("%lld",&t[k]);
return;
}
build(lt,l,mid),build(rt,mid+1,r);
t[k]=t[lt]+t[rt];
return;
}
void change(int k,int l,int r,int ql,int qr){
if (l>qr||r<ql||r-l+1==t[k]) return;
if (l==r&&ql<=l&&r<=qr){
t[k]=(long long)sqrt(t[k]);
return;
}
change(lt,l,mid,ql,qr),change(rt,mid+1,r,ql,qr);
t[k]=t[lt]+t[rt];
return;
}
long long query(int k,int l,int r,int ql,int qr){
if (l>qr||r<ql) return 0;
if (l>=ql&&r<=qr) return t[k];
return query(lt,l,mid,ql,qr)+query(rt,mid+1,r,ql,qr);
}
int main(void){
while (scanf("%lld",&n)>0){
build(1,1,n);
scanf("%lld",&m);
while (m--){
scanf("%lld%lld%lld",&o,&x,&y);
if (x>y) {long long t=x;x=y;y=t;}
switch (o){
case 0:change(1,1,n,x,y);break;
case 1:printf("%lld\n",query(1,1,n,x,y));break;
}
}
}
return 0;
}