• 洛谷 p3870 开关 线段树模板


    这两天学了很长时间于是做了一道水题

    我就用了模板,就连任何优化都没有

    就AC了,复杂度也很爆炸10个点1500多毫秒

    这个题就是把lazy[]改成记录下修改的次数,每次修改的时候mod 2,因为反过来再返回去就一样了

    修改变成

    	sum[root] = r - l + 1 - sum[root];
    

    其他的几乎就没区别了

    #include<bits/stdc++.h>
    
    using namespace std;
    
    inline int read(){int s=0,w=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();return s*w;}
    inline void write(int x) {if(x<0) putchar('-'),x=-x; if(x>9) write(x/10); putchar(x%10+'0'); }
    
    int sum[400010],lazy[400010];
    
    void add(int root,int l,int r,int k){
    	if(k == 0)//如果不修改的话直接退出就好了
    		return ;
    	lazy[root] += k;//记录次数
    	sum[root] = r - l + 1 - sum[root];//修改
    	lazy[root] %= 2;//2以外的毫无意义
    	return ;
    }
    
    void putdown(int root,int l,int r){
    	if(lazy[root] == 0)//没有标记不下发
    		return ;
    	int mod = lazy[root] % 2; int mid = (l + r) >> 1;
    	add(root * 2,l,mid,mod);//左右孩子下发
    	add(root * 2 + 1,mid + 1,r,mod);
    	lazy[root] = 0;//标记清空
    	return ;
    }
    
    void change(int root,int l,int r,int x,int y){
    	if(l > y || r < x)//不在范围内退出(好像没必要)
    		return ;
    	if(l >= x && r <= y){//完全在范围内就标记然后下发
    		add(root,l,r,1);
    		return ;
    	}
    	int mid = (l + r) >> 1;
    	putdown(root,l,r);//标记不到正确位置就继续发
    	int left = root << 1;
    	int right = left + 1;
    	if(x <= mid) change(left,l,mid,x,y);
    	if(mid < y) change(right,mid + 1,r,x,y);
    	sum[root] = sum[left] + sum[right];//更新父节点
    }
    
    int find(int root,int l,int r,int x,int y){
    	if(l >= x && r <= y){//完全包含加上返回
    		return sum[root];
    	}
    	int mid = (l + r) >> 1,ans = 0;
    	int left = root << 1;
    	int right = left + 1;
    	putdown(root,l,r);//传到需要的地方
    	if(x <= mid) ans += find(left,l,mid,x,y);
    	if(mid < y) ans += find(right,mid + 1,r,x,y);
    	return ans;
    }
    
    int main(){
    	int n,m;
    	cin >> n >> m;
    	for(int i = 1; i <= m;++i){
    		int x,y,z;
    		scanf("%d%d%d",&x,&y,&z);
    		if(x == 0){
    			change(1,1,n,y,z);
    		}
    		else{
    			write(find(1,1,n,y,z));
    			cout<<endl;
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    Linux下vsftpd的安装,Java上传文件实现。
    springboot整合shiro、redis及相关优化
    spring boot 配置文件
    spring boot 解决跨域访问
    spring-boot与spring-data-JPA的简单整合
    QQ空间里的“可能认识的人”深层思考????
    unix
    linux
    Linux中fork()函数详解
    word is too tall: try to use less letters, smaller font or bigger background 报错 java程序 验证码不显示
  • 原文地址:https://www.cnblogs.com/lztzs/p/11112136.html
Copyright © 2020-2023  润新知