zoukankan      html  css  js  c++  java
  • P3870 [TJOI2009]开关

    传送门

    算法分析

    • 很简单一个题 线段树啥的可以直接碾过去 (瞎搞应该也能过) 但是为了练分块还是打了打分块
    • 首先考虑分块大小 显然还是 √n 大小 然后将bel预处理好 就可以直接做了
    • 对于每次修改 如果左端点和右端点在同一个块里 一样暴力处理 然后暴力处理左端点的块 暴力处理右端点的块 再处理中间端点的块
    • 这里注意记录一个sum 表示当前块一共有多少个灯开着 然后记录一个lazy 表示是否对当前块进行过0处理
    • 显然如果对于一个块我们处理了两次 那么和没处理过一样 所以我们直接每次让lazy ^ 1 就好了
    • 对于每次询问 暴力处理左端点右端点 对于中间部分 如果lazy为1 则让答案加上size - sum 如果lazy为0 就让答案加上sum

    Code

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn = 1e5 + 10;
    
    int size;
    int bel[maxn];
    int a[maxn],sum[maxn];
    int lazy[maxn];
    
    void change(int l,int r){
    	if(bel[l] == bel[r]) {
    		for(int i = l;i <= r;++i) {
    			a[i] ^= 1;
    			if(a[i] == 1) sum[bel[i]]++;
    			else sum[bel[i]]--;
    		}
    		return;
    	}
    	for(int i = l;i <= bel[l] * size;++i) {
    		a[i] ^= 1;
    		if(a[i] == 1) sum[bel[i]]++;
    		else sum[bel[i]]--;
    	}
    	for(int i = r;i >= (bel[r] - 1) * size + 1;--i) {
    		a[i] ^= 1;
    		if(a[i] == 1) sum[bel[i]]++;
    		else sum[bel[i]]--;
    	}
    	for(int i = bel[l] + 1;i <= bel[r] - 1;++i) lazy[i] ^= 1;
    }
    
    void ask(int l,int r){
    	int ans = 0;
    	if(bel[l] == bel[r]){
    		for(int i = l;i <= r;++i) ans += a[i] ^ lazy[bel[i]];
    		printf("%d
    ",ans);
    		return;
    	}
    	for(int i = l;i <= bel[l] * size;++i) ans += a[i] ^ lazy[bel[i]];
    	for(int i = r;i >= (bel[r] - 1) * size + 1;--i) ans += a[i] ^ lazy[bel[i]];
    	for(int i = bel[l] + 1;i <= bel[r] - 1;++i) {
    		if(lazy[i]) ans += size - sum[i];
    		else ans += sum[i];
    	}
    	printf("%d
    ",ans);
    	return;
    }
    
    int main(){
    	int n,m;scanf("%d%d",&n,&m);
    	size = sqrt(n);
    	for(int i = 1;i <= n;++i) bel[i] = (i - 1) / size + 1;
    	for(int i = 1;i <= m;++i) {
    		int flag,l,r;scanf("%d%d%d",&flag,&l,&r);
    		if(flag == 0) change(l,r);
    		if(flag == 1) ask(l,r);
    	}
    	return 0;
    }
    
    如初见 与初见
  • 相关阅读:
    设计带构造函数的Dog类 代码参考
    动态生成Person类的对象 代码参考
    Fragment传值
    Fragment的创建
    显示Intent和隐式Intent
    Intent及其七大属性及intent-filter设置
    Activity传值的几种方式
    认识Activity
    GridView的基本使用
    Spinner的基本使用
  • 原文地址:https://www.cnblogs.com/HISKrrr/p/13629247.html
Copyright © 2011-2022 走看看