zoukankan      html  css  js  c++  java
  • BZOJ5312 冒险 势能分析、线段树

    传送门


    区间位赋值、区间求最大值似乎是不能够像一般的线段树一样直接打标记的,但是直接暴力也太没有面子了

    我们考虑优化一下暴力:如果说线段树的一段区间内在当前修改的所有位置上所有数都是相同的,那么这个最大值就是可以直接维护的,在上面打上标记;如果这个条件不满足就暴力向下递归。

    然后交一发发现过了!然而这并不是数据水。

    考虑势能分析计算复杂度。设每一个节点的势能函数为当前区间的所有数在位置上不全相同的位置个数。每一次在找到覆盖区间之后暴力向下递归,则势能函数必定减小至少(1),而势能的增加量最多为(log nlog w),所以总的复杂度是(O(nlog nlog w))

    #include<bits/stdc++.h>
    using namespace std;
    
    int read(){
    	int a = 0; char c = getchar(); bool f = 0;
    	while(!isdigit(c)){f = c == '-'; c = getchar();}
    	while(isdigit(c)){
    		a = a * 10 + c - 48; c = getchar();
    	}
    	return f ? -a : a;
    }
    
    const int _ = 2e5 + 3 , MX = (1 << 20) - 1;
    namespace segt{
    	int mx[_ << 2] , mrkand[_ << 2] , mrkor[_ << 2] , vis[_ << 2];
    	
    #define mid ((l + r) >> 1)
    #define lch (x << 1)
    #define rch (x << 1 | 1)
    
    	void mark(int x , int And , int Or){
    		mrkor[x] ^= mrkor[x] & And; mrkand[x] ^= mrkand[x] & Or;
    		mrkor[x] |= Or; mrkand[x] |= And; mx[x] = mx[x] & ~And | Or;
    	}
    	void down(int x){mark(lch , mrkand[x] , mrkor[x]); mark(rch , mrkand[x] , mrkor[x]); mrkand[x] = mrkor[x] = 0;}
    	
    	void init(int x , int l , int r){
    		if(l == r){mx[x] = read(); vis[x] = MX;}
    		else{
    			init(lch , l , mid); init(rch , mid + 1 , r);
    			mx[x] = max(mx[lch] , mx[rch]); vis[x] = vis[lch] & vis[rch] & ~(mx[lch] ^ mx[rch]);
    		}
    	}
    	
    	void modify(int x , int l , int r , int L , int R , int And , int Or){
    		if(l >= L && r <= R && ((vis[x] & And) == And) && ((vis[x] & Or) == Or)){mark(x , And , Or); return;}
    		down(x); if(mid >= L) modify(lch , l , mid , L , R , And , Or);
    		if(mid < R) modify(rch , mid + 1 , r , L , R , And , Or);
    		mx[x] = max(mx[lch] , mx[rch]); vis[x] = vis[lch] & vis[rch] & ~(mx[lch] ^ mx[rch]);
    	}
    
    	int qry(int x , int l , int r , int L , int R){
    		if(l >= L && r <= R) return mx[x];
    		int mx = 0; down(x);
    		if(mid >= L) mx = qry(lch , l , mid , L , R);
    		if(mid < R) mx = max(mx , qry(rch , mid + 1 , r , L , R));
    		return mx;
    	}
    }using namespace segt;
    
    int main(){
    #ifndef ONLINE_JUDGE
    	freopen("in","r",stdin);
    	freopen("out","w",stdout);
    #endif
    	int N = read() , M = read() , l , r , x; init(1 , 1 , N);
    	while(M--)
    		switch(read()){
    		case 1:
    			l = read(); r = read(); x = read(); modify(1 , 1 , N , l , r , MX ^ x , 0);
    			break;
    		case 2:
    			l = read(); r = read(); x = read(); modify(1 , 1 , N , l , r , 0 , x);
    			break;
    		case 3:
    			l = read(); r = read(); printf("%d
    " , qry(1 , 1 , N , l , r));
    		}
    	return 0;
    }
    
  • 相关阅读:
    类数据源Visual C++对ODBC数据库资源的访问
    变量对话框MFC 关于控件变量的使用
    S3C2440上LCD驱动(FrameBuffer)实例开发讲解(二)
    设备内存缓冲区和 /proc/iomem
    multiplexed pins
    电脑硬件资源有冲突怎么处理?
    redhat open source university 硬件资源
    深入理解linux系统下proc文件系统内容
    S3C2440上LCD驱动(FrameBuffer)实例开发讲解(一)
    Framebuffer文章收集
  • 原文地址:https://www.cnblogs.com/Itst/p/11508387.html
Copyright © 2011-2022 走看看