[bzoj-3211]花神游历各国 题解

来源:互联网 发布:怎样学好c语言 编辑:程序博客网 时间:2024/06/10 07:00

题目传送门
题意解析:题目就是告诉你n个数,然后有m个询问,每次询问有两个操作,一个是把一段区间内的和输出,一个是把一段区间中的每个数取根号。


My opinion:看到这题就应该知道应该用数据结构维护,不过这个根号该怎么办呢?我们都知道,根号让一个数降下来只需要几次就好了,而根号1或者0都不会变的,我算了一下让10^9变成1或0只需要根号5次就好了,所以,我们可以每次暴力根号,如果一段区间已经全部变成了0或1就不需要更改。那么就是剩下用什么数据结构了,当然是线段树或者分块了,然而有dalao跟我说分块超时(我没有试过),所以就直接写线段树了。
总结:
1、建树。
2、每次暴力维护,查询依旧。
对,没了,就这么些。


代码:

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<queue>#define rep(i,a,n) for (int i=a;i<=n;i++)#define per(i,a,n) for (int i=a;i>=n;i--)#define Clear(a,x) memset(a,x,sizeof(a))#define ll long long#define INF 2000000000#define eps 1e-8#define LEFT root<<1#define RIGHT root<<1|1#define Left root<<1,l,mid#define Right root<<1|1,mid+1,rusing namespace std;int read(){    int x=0,f=1;    char ch=getchar();    while (ch<'0'||ch>'9') f=ch=='-'?-1:f,ch=getchar();    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();    return x*f;}const int maxn=100005;ll sum[maxn<<2];bool xyf[maxn<<2];int a[maxn];int n;void up(int root){    sum[root]=sum[LEFT]+sum[RIGHT];    xyf[root]=xyf[LEFT]&xyf[RIGHT];}void build(int root,int l,int r){    if (l==r){        sum[root]=a[l];        if (a[l]==0||a[l]==1) xyf[root]=1;            else xyf[root]=0;        return;    }    int mid=(l+r)>>1;    build(Left);    build(Right);    up(root);}ll find(int root,int l,int r,int x,int y){    if (l>y||x>r) return 0;    if (l==x&&r==y) return sum[root];    int mid=(l+r)>>1;    if (y<=mid) return find(Left,x,y);        else if (x>mid) return find(Right,x,y);            else return find(Left,x,mid)+find(Right,mid+1,y);}void change(int root,int l,int r,int x,int y){    if (l>y||x>r) return;    if (l==x&&r==y&&xyf[root]) return;    if (l==r){        a[l]=floor(sqrt(a[l]));        sum[root]=a[l];        if (a[l]==0||a[l]==1) xyf[root]=1;        return;    }    int mid=(l+r)>>1;    if (y<=mid) change(Left,x,y);        else if (x>mid) change(Right,x,y);            else{                change(Left,x,mid);                change(Right,mid+1,y);            }    up(root);}int main(){    n=read();    rep(i,1,n) a[i]=read();    build(1,1,n);    int q=read();    while (q--){        int op=read(),l=read(),r=read();        if (op==1) printf("%lld\n",find(1,1,n,l,r));            else change(1,1,n,l,r);    }    return 0;}

附上AC记录:
这里写图片描述

原创粉丝点击