码迷,mamicode.com
首页 > 其他好文 > 详细

Can you answer these queries? (线段树

时间:2019-01-23 13:59:23      阅读:169      评论:0      收藏:0      [点我收藏+]

标签:upd   inf   string   include   down   acm   节点   math   printf   

 

题目

 

题意:

  初始给你n个数,通过m个操作,  操作0是使区间范围内的每一个a[i]都变成 根号a[i] ,操作1是查询区间范围内数字的和。

 

思路:

  如果一个节点sum[rt]是1的话,根号1还是1,重复遍历这个节点会大大增加计算次数。n和区间左右端点的范围都 <=1e5,所以一个节点最多遍历不超过10次。

  如果这个节点sum[rt]是1,那么标记这个节点vis[rt]=1,说明这个节点以后不用往下遍历了。如果一个节点的左右子节点vis[rt<<1]=1, vis[rt<<1|1]==1,那么vis[rt]=1。注意longlong 以及输入要多空一行。

 

#include<iostream>
#include<cstdio>
#include <cctype>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<string>
#include<cmath>
#include<set>
#include<vector>
#include<stack>
#include<queue>
#include<map>
using namespace std;
#define ll long long
#define mem(a,x) memset(a,x,sizeof(a))
#define se second
#define fi first
const ll mod=1e9+7;
const int INF= 0x3f3f3f3f;
const int N=1e5+5;

ll add[N<<2],sum[N<<2];
ll a[N<<1];
int vis[N<<2];
 
/*
struct node
{
    int v,p;
}b[N<<2];

bool cmp(node x,node y)
{
    return x.v<y.v;
}*/

void push_up(int rt)
{
    sum[rt] = sum[rt<<1] + sum[rt<<1|1] ;
    vis[rt] = vis[rt<<1] & vis[rt<<1|1] ; //左右子节点的vis都是1 父节点才是1 
}
/*
void push_down(int rt,int ln ,int rn)
{
    if(add[rt])
    {
        add[rt<<1]=add[rt<<1|1]=add[rt];
        sum[rt<<1]=add[rt]*ln;
        sum[rt<<1|1]=add[rt]*rn;
        add[rt]=0;
    }
}*/
void Built(int l,int r,int rt)
{
    if(l==r)
    {
        sum[rt]=a[l];
        if(sum[rt]<=1) vis[rt]=1;
        return;
    }
    int m=l+r>>1;
    Built(l,m,rt<<1);
    Built(m+1,r,rt<<1|1);
    push_up(rt);
}

void update(int x,int y,int l,int r,int rt)
{
    if(l==r)
    {
        sum[rt]= 1LL*sqrt(sum[rt]*1.0);
        if( sum[rt]<=1 ) vis[rt]=1;
        return;
    }
    int m=l+r>>1;
    //push_down(rt,m-l+1,r-m);
    if(x<=m && !vis[rt<<1]) update(x,y,l,m,rt<<1);
    if(m<y && !vis[rt<<1|1]) update(x,y,m+1,r,rt<<1|1);
    push_up(rt);
}

ll Query(int x,int y, int l,int r,int rt)
{
    if(x<=l && r<=y)
    {
        return sum[rt];
    }
    int m=l+r>>1;
    //push_down(rt,m-l+1,r-m);
    ll ans=0;
    if(x<=m) ans+=Query(x,y,l,m,rt<<1);
    if(m<y) ans+=Query(x,y,m+1,r,rt<<1|1);
    return ans;
}
int main()
{
    int x,y,c=0,n,m,q;
       while(~scanf("%d",&n) )
       {
           /*for(int i=1;i<=n;i++) scanf("%d",&b[i].v),b[i].p=i;
           sort(b+1,b+1+n,cmp);
        int cnt=0;
        for(int i=1;i<=n;i++)
        {
            if(b[i].v != b[i-1].v)
                cnt++;
               a[b[i].p]=cnt;
           }//离散化完毕  */
           for(int i=1;i<=n;i++)  scanf("%lld",&a[i]);
        mem(vis,0);
        mem(sum,0);
           Built(1,n,1);
           scanf("%d",&m);
           printf("Case #%d:\n",++c);
        while(m--)
        {
            scanf("%d%d%d",&q,&x,&y);
            if(x>y) swap(x,y);
            if(q==0)
                update(x,y,1,n,1);
            else
                printf("%lld\n",Query(x,y,1,n,1) );
        }
        cout<<endl;
    }
   
}

 

Can you answer these queries? (线段树

标签:upd   inf   string   include   down   acm   节点   math   printf   

原文地址:https://www.cnblogs.com/thunder-110/p/10308275.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!