zoukankan      html  css  js  c++  java
  • 【UOJ228】基础数据结构练习题[线段树]

    【UOJ228基础数据结构练习题】

    ==看到开根 第一反应之前那个区间开根 每个数最多只会开5次

    可是这题又有加法操作 如果这次开完 下一次又加回来不断循环就爆炸了

    如果一段区间的数开方后减少的值相同 我们就可以转化为区间减法 这样复杂度就可以保证了==

    比如8 9开方后是2 3减少的值都为6

    所以线段树还要再维护区间最大和最小 每次开方时特判其减少的值是否相等

    yyb大佬的总结

    这类题目的重点在于这些特殊操作的处理

    此时的思考的主要方向已经不是线段树如何使用了

    而是想清楚当前操作具有的特殊性质

    再来相应地在线段树上维护所需要的东西

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define Max(x,y) ((x)>(y)?(x):(y))
    #define Min(x,y) ((x)>(y)?(y):(x))
    #define ls (o<<1)
    #define rs (o<<1|1)
    const int N=1e5+5,M=32000+5,inf=0x3f3f3f3f;
    int n,m,a[N],b[N];
    template <class t>void rd(t &x){
        x=0;int w=0;char ch=0;
        while(!isdigit(ch)) w|=ch=='-',ch=getchar();
        while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
        x=w?-x:x;
    }
    
    struct node{ll mx,mn,add,sum;}t[N<<2];
    void pup(int o){
    	t[o].sum=t[ls].sum+t[rs].sum;
    	t[o].mx=Max(t[ls].mx,t[rs].mx);
    	t[o].mn=Min(t[ls].mn,t[rs].mn);
    }
    void updnode(int o,int l,int r,ll k){
    	t[o].sum+=(ll)(r-l+1)*k;
    	t[o].add+=k,t[o].mn+=k,t[o].mx+=k;
    }
    void pudw(int o,int l,int r){
    	int mid=l+r>>1;
    	if(t[o].add!=0) updnode(ls,l,mid,t[o].add),updnode(rs,mid+1,r,t[o].add),t[o].add=0;
    }
    
    void upd1(int o,int l,int r,int x,int y,ll k){
    	if(l>y||r<x) return;
    	if(x<=l&&r<=y){updnode(o,l,r,k);return;}
    	pudw(o,l,r);
    	int mid=l+r>>1;
    	upd1(ls,l,mid,x,y,k),upd1(rs,mid+1,r,x,y,k);
    	pup(o);
    }
    void upd2(int o,int l,int r,int x,int y){
    	if(l>y||r<x) return;
    	if(x<=l&&r<=y){
    		ll A=t[o].mn-(ll)sqrt(t[o].mn),B=t[o].mx-(ll)sqrt(t[o].mx);
    		if(A==B){updnode(o,l,r,-A);return;}
    	}
    	pudw(o,l,r);
    	int mid=l+r>>1;
    	upd2(ls,l,mid,x,y),upd2(rs,mid+1,r,x,y);
    	pup(o);
    }
    ll query(int o,int l,int r,int x,int y){
    	if(l>y||r<x) return 0;
    	if(x<=l&&r<=y) return t[o].sum;
    	pudw(o,l,r);
    	int mid=l+r>>1;ll ans=0ll;
    	ans+=query(ls,l,mid,x,y)+query(rs,mid+1,r,x,y);
    	pup(o);
    	return ans;
    }
    void build(int o,int l,int r){
    	t[o].add=0;
    	if(l==r){t[o].mn=t[o].mx=t[o].sum=a[l];return;}
    	int mid=l+r>>1;
    	build(ls,l,mid),build(rs,mid+1,r);
    	pup(o);
    }
    
    int main(){
    	freopen("in.txt","r",stdin);
    //	freopen("numbers.out","w",stdout);
    	rd(n),rd(m);
    	for(int i=1;i<=n;++i) rd(a[i]);
    	build(1,1,n);
    	for(int i=1,opt,x,y,k;i<=m;++i){
    		rd(opt),rd(x),rd(y);
    		if(opt==1)
    			rd(k),upd1(1,1,n,x,y,k);
    		else if(opt==2) upd2(1,1,n,x,y);
    		else printf("%lld
    ",query(1,1,n,x,y));
    	}
        return 0;
    }
    
  • 相关阅读:
    "无法在证书存储区中找到清单签名证书"的解决办法
    Windows消息ID说明
    ToolBar来的是什么事. (ToolBar 难见的Bug)
    SQL Tips 收集常用的SQL
    郁闷的内存泄露,增加TmfEditFormCmptMgr.OnDstMainSetFieldData惹的祸
    FormDestroy和Destroy中选其一个使用.
    一步步教你优化Delphi字串查找(转载)
    利用SQL建立数据库对象
    数据字典ChangeName引发的问题.
    测试Live Writer
  • 原文地址:https://www.cnblogs.com/lxyyyy/p/11446912.html
Copyright © 2011-2022 走看看