zoukankan      html  css  js  c++  java
  • [做题记录-数据结构] [Ynoi2007] rgxsxrs

    把值域按照(2^0, 2^1, 2^2,cdots2^k)分块, 每个块里面维护一个线段树每次对于值分类讨论然后暴力维护, 复杂度均摊正确。

    为了常数, 需要线段树底层分块, 需要调参。

    这个分块比较妙妙。

    #include <bits/stdc++.h>
    #include <bits/extc++.h>
    
    using namespace std;
     using namespace __gnu_pbds;
    
    class Input {
    	#define MX 1000000
    	private :
    		char buf[MX], *p1 = buf, *p2 = buf;
    		inline char gc() {
    			if(p1 == p2) p2 = (p1 = buf) + fread(buf, 1, MX, stdin);
    			return p1 == p2 ? EOF : *(p1 ++);
    		}
    	public :
    		Input() {
    			#ifdef Open_File
    				freopen("a.in", "r", stdin);
    				freopen("a.out", "w", stdout);
    			#endif
    		}
    		template <typename T>
    		inline Input& operator >>(T &x) {
    			x = 0; int f = 1; char a = gc();
    			for(; ! isdigit(a); a = gc()) if(a == '-') f = -1;
    			for(; isdigit(a); a = gc()) 
    				x = x * 10 + a - '0';
    			x *= f;
    			return *this;
    		}
    		inline Input& operator >>(char &ch) {
    			while(1) {
    				ch = gc();
    				if(ch != '
    ' && ch != ' ') return *this;
    			}
    		}
    		inline Input& operator >>(char *s) {
    			int p = 0;
    			while(1) {
    				s[p] = gc();
    				if(s[p] == '
    ' || s[p] == ' ' || s[p] == EOF) break;
    				p ++; 
    			}
    			s[p] = '';
    			return *this;
    		}
    	#undef MX
    } Fin;
    
    class Output {
    	#define MX 1000000
    	private :
    		char ouf[MX], *p1 = ouf, *p2 = ouf;
    		char Of[105], *o1 = Of, *o2 = Of;
    		void flush() { fwrite(ouf, 1, p2 - p1, stdout); p2 = p1; }
    		inline void pc(char ch) {
    			* (p2 ++) = ch;
    			if(p2 == p1 + MX) flush();
    		}
    	public :
    		template <typename T> 
    		inline Output& operator << (T n) {
    			if(n < 0) pc('-'), n = -n;
    			if(n == 0) pc('0');
    			while(n) *(o1 ++) = (n % 10) ^ 48, n /= 10;
    			while(o1 != o2) pc(* (--o1));
    			return *this; 
    		}
    		inline Output & operator << (char ch) {
    			pc(ch); return *this; 
    		}
    		inline Output & operator <<(const char *ch) {
    			const char *p = ch;
    			while( *p != '' ) pc(* p ++);
    			return * this;
    		}
    		~Output() { flush(); } 
    	#undef MX
    } Fout;
    
    #define cin Fin
    #define cout Fout
    #define endl '
    '
    
    using LL = long long;
    using uint = unsigned int;
    
    const int N = 5e5 + 10;
    const int INF = (1u << 31) - 1;
    const int Lower_Block = 512;
    
    struct AnsPair {
    	LL sum;
    	int mn, mx;
    	AnsPair(LL _sum = 0, int _mn = 0, int _mx = 0) : sum(_sum), mn(_mn), mx(_mx) {} 
    } ;
    
    inline AnsPair merge(AnsPair a, AnsPair b) {
    	return AnsPair(a.sum + b.sum, min(a.mn, b.mn), max(a.mx, b.mx));
    }
    
    struct Node {
        Node * ls, * rs;
        int mn, mx, sz, l, r;
        LL sum, tag;
        vector<pair<int, int> > vec;
        Node() { ls = rs = NULL; l = r = 0; mn = INF; mx = sz = sum = tag = 0; }
        Node(int _l, int _r) : l(_l), r(_r) { ls = rs = NULL; mn = INF; mx = sz = sum = tag = 0; }
    	void clear() { ls = rs = NULL; l = r = 0; mn = INF; mx = sz = sum = tag = 0; }
    	bool isleaf() { return r - l + 1 <= Lower_Block; }
        void upd() {
            if(r - l + 1 <= Lower_Block) {
           		mn = INF; mx = 0; sz = vec.size(); sum = 0;
                for(auto it : vec) mn = min(it.second, mn), mx = max(it.second, mx), sum += it.second;
                return ;
            }
    		mn = INF; mx = 0; sz = 0; sum = 0;
    		if(ls != NULL) mn = min(mn, ls -> mn), mx = max(mx, ls -> mx), sz += ls -> sz, sum += ls -> sum;
    		if(rs != NULL) mn = min(mn, rs -> mn), mx = max(mx, rs -> mx), sz += rs -> sz, sum += rs -> sum;
        }
        void leafdown(LL val) {
            for(auto &it : vec) it.second += val; this -> upd(); 
        }
        void nodedown(LL val) {
            mn += val; mx += val; sum += sz * val; tag += val;
        }
        void modify(LL val) {
            if(r - l + 1 <= Lower_Block) this -> leafdown(val);
            else this -> nodedown(val);
        }
        void pushdown() {
            if(tag) {
                if(ls != NULL) ls -> modify(tag); 
    			if(rs != NULL) rs -> modify(tag);
                tag = 0;
            }   
        }
    } ;
    
    int n;
    
    class SegmentTree {
    	private :
    		Node * root;
    		void update(Node *&x, int l, int r, int L, int R, LL v) {
    			if(x == NULL) x = new Node(l, r);
    			if(x -> mx <= v) return ;
    			if(L <= l && r <= R && x -> mn > v) {
    				x -> modify(- v); return ;
    			} 
    			if(x -> isleaf()) {
    				for(auto &it : x -> vec) 
    					if(L <= it.first && it.first <= R && it.second > v)  it.second -= v;
    				x -> upd(); return ;
    			}
    			x -> pushdown();
    			int mid = (l + r) >> 1;
    			if(L <= mid) update(x -> ls, l, mid, L, R, v);
    			if(R >  mid) update(x -> rs, mid + 1, r, L, R, v);
    			x -> upd();
    		}
    		AnsPair range_qry(Node *&x, int l, int r, int L, int R) {
    			if(x == NULL) return AnsPair(0, INF, 0);
    			if(L <= l && r <= R) return AnsPair(x -> sum, x -> mn, x -> mx);
    			if(x -> isleaf()) {
    				LL sum = 0; int mn = INF, mx = 0;
    				for(auto & it : x -> vec) if(L <= it.first && it.first <= R) {
    					sum += it.second;
    					mn = min(mn, it.second);
    					mx = max(mx, it.second);
    				}
    				return AnsPair(sum, mn, mx);
    			}
    			x -> pushdown();
    			int mid = (l + r) >> 1;
    			if(R <= mid) return range_qry(x -> ls, l, mid, L, R);
    			if(L > mid) return range_qry(x -> rs, mid + 1, r, L, R);
    			return merge(range_qry(x -> ls, l, mid, L, R), range_qry(x -> rs, mid + 1, r, L, R));
    		}
    		void DeleteNode(Node *&x, int l, int r, int lim, vector<pair<int, int> > &vec) {
    			if(x == NULL) return ;
    			if(x -> mn >= lim) return ;
    			if(x -> isleaf()) {
    				static vector<pair<int, int> > clr;
    				clr.clear();
    				for(auto it : x -> vec) 
    					if(it.second < lim) vec.push_back(it); 
    					else clr.push_back(it);
    				x -> vec = clr;
    				x -> upd();
    				if(x -> sz == 0) delete x, x = NULL; return ;
    			}
    			x -> pushdown();
    			int mid = (l + r) >> 1;
    			DeleteNode(x -> ls, l, mid, lim, vec);
    			DeleteNode(x -> rs, mid + 1, r, lim, vec);
    			x -> upd();
    			if(x -> sz == 0) delete x, x = NULL;
    		}
    		void insert(Node *&x, int l, int r, int p, int val) {
    			if(x == NULL) x = new Node(l, r);
    			if(x -> isleaf()) {
    				x -> vec.push_back( {p, val} );
    				x -> upd();
    				return ;
    			}
    			x -> pushdown();
    			int mid = (l + r) >> 1;
    			if(p <= mid) insert(x -> ls, l, mid, p, val);
    			else insert(x -> rs, mid + 1, r, p, val);
    			x -> upd();
    		}
    	public :
    		SegmentTree() : root(NULL) {}
    		void Insert(int p, int val) { insert(root, 1, n, p, val);  }
    		void Update(int L, int R, LL val) { update(root, 1, n, L, R, val); }
    		void Delete(int lim, vector<pair<int, int> > &vec) { DeleteNode(root, 1, n, lim, vec); }
    		AnsPair Qry(int L, int R) { return range_qry(root, 1, n, L, R); }
    } ;
    
    SegmentTree SGT[10];
    
    int pow16[20];
    
    inline int log16(int x) {
        int t = 0;
        while (t < 7 && pow16[t + 1] <= x) t++;
        return t;
    }
    // log(x - 1)
    
    int main() {
    	pow16[0] = 1;
        for (register int i = 1; i < 8; i ++) pow16[i] = pow16[i - 1] * (1 << 4);
        cin >> n; int m; cin >> m;
    	for(int i = 1; i <= n; i ++) {
    		int x; cin >> x;
    		SGT[log16(x)].Insert(i, x);
    	} 
    	int lastans = 0;
    	while(m --) {
    		int opt;
    		cin >> opt;
    		if(opt == 1) {
    			int l, r, x; cin >> l >> r >> x;
    			l ^= lastans; r ^= lastans; x ^= lastans;
    			vector<pair<int, int> > clr;
    			for(int i = 0; i < 8; i ++) SGT[i].Update(l, r, x), SGT[i].Delete(1 << (4 * i), clr);
    			for(auto it : clr) SGT[log16(it.second)].Insert(it.first, it.second);
    		}
    		else {
    			int l, r; cin >> l >> r;
    			l ^= lastans; r ^= lastans;
    			AnsPair ans = AnsPair(0, INF, 0);
    			for(int i = 0; i < 8; i ++) ans = merge(ans, SGT[i].Qry(l, r));
    			cout << ans.sum << ' ' << ans.mn << ' ' << ans.mx << endl;
    			lastans = ans.sum & ((1 << 20) - 1);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    关于在组件GIS开发中使用Python的一点补充说明
    shell环境变量以及set,env,export的区别
    快速配置 Samba 将 Linux 目录映射为 Windows 驱动器
    Expect 教程中文版
    rpm 包管理
    .bash_profile和.bashrc的什么区别
    grep 零宽断言
    自动化测试
    dialog shell下的gui设计 代替繁杂libncurses编程
    x11 gtk qt gnome kde 之间的区别和联系
  • 原文地址:https://www.cnblogs.com/clover4/p/15257087.html
Copyright © 2011-2022 走看看