zoukankan      html  css  js  c++  java
  • LOJ#6507. 「雅礼集训 2018 Day7」A 题解

    题目链接

    直接线段树上打(tag)即可,如果遇到打tag之后存在不同的值的区间,那么就往下递归。

    复杂度分析 :

    记一个节点的势能 (f(node) = sumlimits_{i=0}^{31} g(node,i),)其中 (g(node,i)) 表示 (node) 节点内部的所有数字中,第 (i) 个二进制位上是(1)/否(0)有不同的值。

    一开始势能是 (O(nlog n imes 31)) 的。

    每次修改最多增加(O(log n imes 31)) 的势能,过程中如果暴力递归了一次那么势能必然也会减去1,所以复杂度为(O((n+m) log n imes 31).)

    code :

    #include <bits/stdc++.h>
    using namespace std;
    template <typename T> void read(T &x){
    	static char ch; x = 0,ch = getchar();
    	while (!isdigit(ch)) ch = getchar();
    	while (isdigit(ch)) x = x * 10 + ch - '0',ch = getchar();
    }
    inline void write(int x){ if (x > 9) write(x/10); putchar(x%10+'0'); }
    const int N = 524288 + 1,ALL = (1ll<<31)-1;
    int n,a[N];
    struct Node{
    	int mn,v0,v1;
    }t[N<<2];
    #define lc o<<1
    #define rc o<<1|1
    inline void up(int o){
    	t[o].v1 = t[lc].v1 & t[rc].v1,t[o].v0 = t[lc].v0 & t[rc].v0,t[o].mn = min(t[lc].mn,t[rc].mn);
    }
    inline void Build(int o,int l,int r){
    	if (l == r){ t[o].mn = t[o].v1 = a[l],t[o].v0 = ALL^a[l]; return; }
    	int mid = l+r>>1; Build(lc,l,mid); Build(rc,mid+1,r); up(o); 
    }
    inline void down(int o){
    	if ((t[o].v0 | t[o].v1) == ALL) t[lc] = t[rc] = t[o];
    }
    int ll,rr;
    inline void Or(int o,int l,int r,int v){
    	v &= ALL ^ t[o].v1; if (!v) return;
    	if (ll <= l && rr >= r){
    		if ((v | t[o].v1 | t[o].v0) == ALL){
    			t[o].v1 |= v,t[o].v0 = ALL ^ t[o].v1,t[o].mn = t[o].v1; return;
    		}
    		down(o); int mid = l+r>>1; Or(lc,l,mid,v); Or(rc,mid+1,r,v); up(o); return;
    	}
    	down(o); int mid = l+r>>1;
    	if (ll <= mid) Or(lc,l,mid,v); if (rr > mid) Or(rc,mid+1,r,v); up(o);
    }
    inline void And(int o,int l,int r,int v){
    	v &= ALL ^ t[o].v0; if (!v) return;
    	if (ll <= l && rr >= r){
    		if ((v | t[o].v1 | t[o].v0) == ALL){
    			t[o].v0 |= v,t[o].v1 = ALL ^ t[o].v0,t[o].mn = t[o].v1; return;
    		}
    		down(o); int mid = l+r>>1; And(lc,l,mid,v); And(rc,mid+1,r,v); up(o); return;
    	}
    	down(o); int mid = l+r>>1;
    	if (ll <= mid) And(lc,l,mid,v); if (rr > mid) And(rc,mid+1,r,v); up(o);
    }
    int qans;
    inline void Ask(int o,int l,int r){
    	if (ll <= l && rr >= r || ALL == (t[o].v0 | t[o].v1)){ qans = min(qans,t[o].mn); return; }
    	int mid = l+r>>1; if (ll <= mid) Ask(lc,l,mid); if (rr > mid) Ask(rc,mid+1,r);
    }
    #undef lc
    #undef rc
    int main(){
    	int i,m,op,x;
    	read(n),read(m); for (i = 1; i <= n; ++i) read(a[i]); Build(1,1,n);
    	while (m--){
    		read(op),read(ll),read(rr); if (op <= 2) read(x);
    		if (op == 1) And(1,1,n,ALL^x);
    		if (op == 2) Or(1,1,n,x);
    		if (op == 3) qans = ALL,Ask(1,1,n),write(qans),putchar('
    ');
    	}
    	return 0;
    }
    
  • 相关阅读:
    nginx访问控制
    nginx的请求限制
    nginx目录及配置语法
    安装Nginx
    Docker Service启动时挂载docker命令
    禁止flyme自动下载rom
    docker.service 修改指南
    debian 10.x (buster) 离线安装docker及卸载
    按照容器名称清除docker容器产生的日志文件内容
    debian修改系统语言为英文
  • 原文地址:https://www.cnblogs.com/s-r-f/p/13619011.html
Copyright © 2011-2022 走看看