zoukankan      html  css  js  c++  java
  • BZOJ3211 花神游历各国

    题目链接:戳我

    想改天把花神题都做了qwqwqwq

    开根号不具有可加性。。所以我们得暴力更改。。也就是说要叶子结点一个一个修改,然后往上面合并。。。。

    但是这样为什么不会T?因为对于一个数,它不需要几次开根号就会变成0或者1,又因为1开根号还是1,0开根号还是0,所以开了就跟没开一样。。。

    所以我们记录一个maxx值,如果当前区间最大数都不超过1了,就放过这个区间吧。。。。

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    #define MAXN 100010
    using namespace std;
    int n,m;
    long long a[MAXN];
    struct Node{int l,r;long long sum,maxx;}t[MAXN<<2];
    inline int ls(int x){return x<<1;}
    inline int rs(int x){return x<<1|1;}
    inline void push_up(int x)
    {   
        t[x].sum=t[ls(x)].sum+t[rs(x)].sum;
        t[x].maxx=max(t[ls(x)].maxx,t[rs(x)].maxx);
    }
    inline void build(int x,int l,int r)
    {
        t[x].l=l,t[x].r=r;
        if(l==r) {t[x].sum=t[x].maxx=a[l];return;}
        int mid=(l+r)>>1;
        build(ls(x),l,mid);
        build(rs(x),mid+1,r);
        push_up(x);
    }
    inline void update(int x,int ll,int rr)
    {
        if(t[x].maxx<=1) return;
        int l=t[x].l,r=t[x].r;
        if(l==r)
        {
            t[x].sum=t[x].maxx=sqrt(t[x].sum);
            return;
        }
        int mid=(l+r)>>1;
        if(ll<=mid) update(ls(x),ll,rr);
        if(mid<rr) update(rs(x),ll,rr);
        push_up(x);
    }
    inline long long query(int x,int ll,int rr)
    {
        int l=t[x].l,r=t[x].r;
        if(ll<=l&&r<=rr) return t[x].sum;
        int mid=(l+r)>>1;
        long long cur_ans=0;
        if(ll<=mid) cur_ans+=query(ls(x),ll,rr);
        if(mid<rr) cur_ans+=query(rs(x),ll,rr);
        return cur_ans;
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        #endif
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
        build(1,1,n);
        scanf("%d",&m);
        for(int i=1;i<=m;i++)
        {
            int op,l,r;
            scanf("%d%d%d",&op,&l,&r);
            if(l>r) swap(l,r);
            if(op==2) update(1,l,r);
            else printf("%lld
    ",query(1,l,r));
        }
        return 0;
    }
    

    update:写完【基础数据结构练习题】之后,这个题算是又有了新的做法(不过代码跑得更慢了。。。但是可以解决区间加的操作并保证正确的时间复杂度)

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define int long long
    #define MAXN 400010
    using namespace std;
    int n,m;
    long long a[MAXN];
    struct Node{int l,r;long long sum,minn,maxx,tag;}t[MAXN<<2];
    inline int ls(int x){return x<<1;}
    inline int rs(int x){return x<<1|1;}
    inline void push_up(int x)
    {
    	t[x].sum=t[ls(x)].sum+t[rs(x)].sum;
    	t[x].maxx=max(t[ls(x)].maxx,t[rs(x)].maxx);
    	t[x].minn=min(t[ls(x)].minn,t[rs(x)].minn);
    }
    inline void f(int x,long long k)
    {
    	t[x].tag+=k;
    	t[x].minn+=k;
    	t[x].maxx+=k;
    	t[x].sum+=k*(t[x].r-t[x].l+1);
    }
    inline void push_down(int x)
    {	
    	if(t[x].tag)
    	{
    		f(ls(x),t[x].tag);
    		f(rs(x),t[x].tag);
    		t[x].tag=0;
    	}
    }
    inline void build(int x,int l,int r)
    {
    	t[x].l=l,t[x].r=r;
    	if(l==r){t[x].sum=t[x].minn=t[x].maxx=a[l];return;}
    	int mid=(l+r)>>1;
    	build(ls(x),l,mid);
    	build(rs(x),mid+1,r);
    	push_up(x);
    }
    inline void update_sqrt(int x,int ll,int rr)
    {
    	int l=t[x].l,r=t[x].r;
    	if(ll<=l&&r<=rr)
    	{
    		long long a=sqrt(t[x].maxx),b=sqrt(t[x].minn);
    		if(t[x].maxx==t[x].minn) {f(x,-t[x].maxx+a);return;}
    		if(t[x].maxx-a==t[x].minn-b) {f(x,-t[x].minn+b);return;}
    	}
    	int mid=(l+r)>>1;
    	push_down(x);
    	if(ll<=mid) update_sqrt(ls(x),ll,rr);
    	if(mid<rr) update_sqrt(rs(x),ll,rr);
    	push_up(x);
    }
    inline long long query(int x,int ll,int rr)
    {
    	int l=t[x].l,r=t[x].r;
    	if(ll<=l&&r<=rr) return t[x].sum;
    	int mid=(l+r)>>1;
    	long long cur_ans=0;
    	push_down(x);
    	if(ll<=mid) cur_ans+=query(ls(x),ll,rr);
    	if(mid<rr) cur_ans+=query(rs(x),ll,rr);
    	return cur_ans;
    }
    signed main()
    {
    	#ifndef ONLINE_JUDGE
    	freopen("ce.in","r",stdin);
    	freopen("ce.out","w",stdout);
    	#endif
    	scanf("%lld",&n);
    	for(int i=1;i<=n;i++) scanf("%lld
    ",&a[i]);
    	scanf("%lld",&m);
    	build(1,1,n);
    	for(int j=1;j<=m;j++)
    	{
    		int op,l,r;
    		scanf("%lld%lld%lld",&op,&l,&r);
    		if(l>r) swap(l,r);
    		if(op==2) update_sqrt(1,l,r);
    		else if(op==1) printf("%lld
    ",query(1,l,r));
    	}
    	return 0;	
    }
    
  • 相关阅读:
    软件开发项目文档模版
    Java Swing 非常漂亮的外观Nimbus使用方法
    周00王总监 宁波浦一的同仁们 有看见的进来
    冰川世界
    君住长江头,我住长江尾,日日思君不见君,共饮长江水
    可乐男孩被保送上大学
    变形金刚2
    爱无罪
    英语习惯口语简写
    看完了团长,我没有心理在去看《南京!南京!》
  • 原文地址:https://www.cnblogs.com/fengxunling/p/10501974.html
Copyright © 2011-2022 走看看