P4145/#6281/GSS4三题题解(线段树区间开根)

前言:

zhx的PPT上的题

三道题思路,做法完全相同,区别在于输入输出格式
同一份代码A掉3个题真捏麻的爽

题目大意:

区间所有数开根号
区间求和

分析:

开根区间内的一个数 \(a_i\) 在不断开根号下取整的过程中是越来越小的。
经过若干次开根最后会变为\(1\) 。其变成 \(1\) 之后就没有必要对它再进行开根操作了。
在线段树每一个节点维护 \(sum ,maxn\) 表示区间最大值和区间和。如果发现这段区间的最大值等于 \(1\) ,那么再次对它开根结果还是 \(1\) ,区间内的每一个数都没有发生变化。
所以如果修改时遇到一个区间为 \(1\) 的区间就可以直接跳过。
如果不为 \(1\) 就暴力开根它的左右儿子。
为什么暴力不会TLE?因为总共 \(n\) 个数,每个数最多开不超过 \(10\) 次。暴力次数为 \(10n\) 。每次暴力无非是从线段树根走到叶。所以最多只会暴力 \(nlog_n\) 次。

代码:

P4145上帝造题的七分钟 2 / 花神游历各国:

#include<bits/stdc++.h>
#define int long long
#define MAXN 1000086

using namespace std;
int n,m ;
int a[MAXN];

struct T{
int l,r,val,maxn;
}t[MAXN];

void update(int node){
    t[node].val=t[node<<1].val+t[node<<1|1].val;
    t[node].maxn=max(t[node<<1].maxn,t[node<<1|1].maxn);
}


void build(int l,int r,int node){
    t[node].l=l;
    t[node].r=r;
    if(l==r){
        t[node].val=a[l];
        t[node].maxn=a[l];
        return ;
    }
    int mid=(l+r)>>1;
    build(l,mid,node<<1);
    build(mid+1,r,node<<1|1);
    update(node);
}

void change(int l,int r,int node){
    if(t[node].l==t[node].r){
        t[node].val=sqrt(t[node].val);
        t[node].maxn=sqrt(t[node].maxn);
        return ;
    }
    int mid=(t[node].l+t[node].r)>>1;
    
    if(l<=mid&&t[node<<1].maxn>1)
    change(l,r,node<<1);
    if(r>mid&&t[node<<1|1].maxn>1)
    change(l,r,node<<1|1);
    update(node);
}

int ask(int l,int r,int node){
    if(l<=t[node].l&&t[node].r<=r){
        return t[node].val;
    }
    int mid=(t[node].l+t[node].r)>>1;
    int ans=0;
    if(l<=mid) ans+=ask(l,r,node<<1);
    if(r>mid) ans+=ask(l,r,node<<1|1);
    return ans;
}



signed main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    cin>>m;
    build(1,n,1);
    int op,l,r;
    for(int i=1;i<=m;i++){
        cin>>op>>l>>r;
        
        if(l>r)swap(l,r);

        if(op==0){
             change(l,r,1);
        }
        else{
            cout<<ask(l,r,1)<<'\n';
        }
    
    }

    return 0;
}

loj#6281 数列分块入门 5:

#include<bits/stdc++.h>
#define int long long
#define MAXN 1000086

using namespace std;
int n,m ;
int a[MAXN];
inline int read(){
	register int x=0;
	register bool f=0;
	register char c=getchar();
	while(c<'0'||c>'9'){
		if(c=='-') f=1;
		c=getchar();
	}
	while(c>='0'&&c<='9'){
		x=(x<<3)+(x<<1)+c-48;
		c=getchar();
	}
	return f?-x:x;
}
struct T{
int l,r,val,maxn;
}t[MAXN];

void update(int node){
    t[node].val=t[node<<1].val+t[node<<1|1].val;
    t[node].maxn=max(t[node<<1].maxn,t[node<<1|1].maxn);
}


void build(int l,int r,int node){
    t[node].l=l;
    t[node].r=r;
    if(l==r){
        t[node].val=a[l];
        t[node].maxn=a[l];
        return ;
    }
    int mid=(l+r)>>1;
    build(l,mid,node<<1);
    build(mid+1,r,node<<1|1);
    update(node);
}

void change(int l,int r,int node){
    if(t[node].l==t[node].r){
        t[node].val=sqrt(t[node].val);
        t[node].maxn=sqrt(t[node].maxn);
        return ;
    }
    int mid=(t[node].l+t[node].r)>>1;
    
    if(l<=mid&&t[node<<1].maxn>1)
    change(l,r,node<<1);
    if(r>mid&&t[node<<1|1].maxn>1)
    change(l,r,node<<1|1);
    update(node);
}

int ask(int l,int r,int node){
    if(l<=t[node].l&&t[node].r<=r){
        return t[node].val;
    }
    int mid=(t[node].l+t[node].r)>>1;
    int ans=0;
    if(l<=mid) ans+=ask(l,r,node<<1);
    if(r>mid) ans+=ask(l,r,node<<1|1);
    return ans;
}



signed main(){
	int cnt=0;
    cin>>n;

    //	printf("Case #%d:\n",++cnt);
		memset(a,0,sizeof(a));
		memset(t,0,sizeof(t));   	
    for(int i=1;i<=n;i++){
        a[i]=read();
    }
    //cin>>m;
    build(1,n,1);
    int op,l,r,c;
    for(int i=1;i<=n;i++){
        op=read();
        l=read();
        r=read();
        c=read();
        if(l>r)swap(l,r);

        if(op==0){
             change(l,r,1);
        }
        else{
            cout<<ask(l,r,1)<<'\n';
        }
    
    }
    cout<<endl;
    

    return 0;
}

SPOJ GSS4 Can you answer these queries IV

洛谷SP2713



#include<bits/stdc++.h>
#define int long long
#define MAXN 1000086

using namespace std;
int n,m ;
int a[MAXN];
inline int read(){
	register int x=0;
	register bool f=0;
	register char c=getchar();
	while(c<'0'||c>'9'){
		if(c=='-') f=1;
		c=getchar();
	}
	while(c>='0'&&c<='9'){
		x=(x<<3)+(x<<1)+c-48;
		c=getchar();
	}
	return f?-x:x;
}
struct T{
int l,r,val,maxn;
}t[MAXN];

void update(int node){
    t[node].val=t[node<<1].val+t[node<<1|1].val;
    t[node].maxn=max(t[node<<1].maxn,t[node<<1|1].maxn);
}


void build(int l,int r,int node){
    t[node].l=l;
    t[node].r=r;
    if(l==r){
        t[node].val=a[l];
        t[node].maxn=a[l];
        return ;
    }
    int mid=(l+r)>>1;
    build(l,mid,node<<1);
    build(mid+1,r,node<<1|1);
    update(node);
}

void change(int l,int r,int node){
    if(t[node].l==t[node].r){
        t[node].val=sqrt(t[node].val);
        t[node].maxn=sqrt(t[node].maxn);
        return ;
    }
    int mid=(t[node].l+t[node].r)>>1;
    
    if(l<=mid&&t[node<<1].maxn>1)
    change(l,r,node<<1);
    if(r>mid&&t[node<<1|1].maxn>1)
    change(l,r,node<<1|1);
    update(node);
}

int ask(int l,int r,int node){
    if(l<=t[node].l&&t[node].r<=r){
        return t[node].val;
    }
    int mid=(t[node].l+t[node].r)>>1;
    int ans=0;
    if(l<=mid) ans+=ask(l,r,node<<1);
    if(r>mid) ans+=ask(l,r,node<<1|1);
    return ans;
}



signed main(){
	int cnt=0;
    while(cin>>n){
    	printf("Case #%d:\n",++cnt);
		memset(a,0,sizeof(a));
		memset(t,0,sizeof(t));   	
    for(int i=1;i<=n;i++){
        a[i]=read();
    }
    cin>>m;
    build(1,n,1);
    int op,l,r;
    for(int i=1;i<=m;i++){
        op=read();
        l=read();
        r=read();
        if(l>r)swap(l,r);

        if(op==0){
             change(l,r,1);
        }
        else{
            cout<<ask(l,r,1)<<'\n';
        }
    
    }
    cout<<endl;
    
}
    return 0;
}
posted @ 2022-09-05 14:10  DAIANZE  阅读(121)  评论(0编辑  收藏  举报