zoukankan      html  css  js  c++  java
  • [做题记录-数据结构][Ynoi 2013 文化课]

    赋值操作可以使得把区间视作多项式实现快速求值。

    操作符推平使用区间和以及区间乘积实现快速求值。

    剩下的注意计算多项式幂次的时候递推计算减少(log), 剩下的是暴力了。

    下面是一份由于没有优化新建空间的过不去代码。

    #include <bits/stdc++.h>
    #include <bits/extc++.h>
    
    using namespace std;
    using namespace __gnu_cxx;
    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() {
    			//#define Open_File
    			#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;
    
    inline int log2(unsigned int x);
    inline int popcount(unsigned x);
    inline int popcount(unsigned long long x);
    template<typename T> struct BinaryQueue;
    template<typename T>struct BinaryQueue {
    	__gnu_pbds :: priority_queue<T, less<T>, binary_heap_tag> q;
    	void push(T x) { q.push(x); }
    	void pop() { q.pop(); }
    } ;
    
    template <int mod>
    class Int {
    	private :
    		inline int Mod(int x) { return x + ((x >> 31) & mod); } 
    		inline int power(int x, int k) {
    			int res = 1;
    			while(k) { 
    				if(k & 1) res = 1LL * x * res % mod;// cerr << k;
    				x = 1LL * x * x % mod; k >>= 1;
    			}
    			return res;
    		}
    	public :
    		int v;
    		Int(int _v = 0) : v(_v) {}
    		operator int() { return v; }
    		
    		inline Int operator =(Int x) { return Int(v = x.v); }
    		inline Int operator =(int x) { return Int(v = x); }
    		inline Int operator *(Int x) { return Int(1LL * v * x.v % mod); }
    		inline Int operator *(int x) { return Int(1LL * v * x % mod); }
    		inline Int operator +(Int x) { return Int( Mod(v + x.v - mod) ); }
    		inline Int operator +(int x) { return Int( Mod(v + x - mod) ); }
    		inline Int operator -(Int x) { return Int( Mod(v - x.v) ); }
    		inline Int operator -(int x) { return Int( Mod(v - x) ); }
    		inline Int operator ~() { return Int(power(v, mod - 2)); }
    		inline Int operator +=(Int x) { return Int(v = Mod(v + x.v - mod)); }
    		inline Int operator +=(int x) { return Int(v = Mod(v + x - mod)); }
    		inline Int operator -=(Int x) { return Int(v = Mod(v - x.v)); }
    		inline Int operator -=(int x) { return Int(v = Mod(v - x)); }
    		inline Int operator *=(Int x) { return Int(v = 1LL * v * x.v % mod); }
    		inline Int operator *=(int x) { return Int(v = 1LL * v * x % mod); }
    		inline Int operator /=(Int x) { return Int(v = v / x.v); }
    		inline Int operator /=(int x) { return Int(v = v / x); }
    		inline Int operator ^(int k) { return Int(power(v, k)); }
    } ;
    
    using mint = Int<(int) (1e9 + 7)>;
    
    const int N = 1e5 + 5;
    
    struct Poly {
    	vector<int> pol;
    	vector<mint> val;
    	int sz;
    	Poly(int _sz = 0) {
    		sz = _sz;
    		//while(val.size() < sz) val.emplace_back(0);
    		//while(pol.size() < sz) pol.emplace_back(0);
    		val.resize(sz); //cerr << sz << endl;
    		pol.resize(sz);
    	}
    	void resize(int _sz) {
    		//vector<int> x;
    		//vector<mint> y;
    		//swap(val, y); swap(pol, x);
    		//val.clear();
    		//pol.clear();
    		sz = _sz;
    		val.resize(sz); //cerr << sz << endl;
    		pol.resize(sz);
    	}
    	void del(int pos) {
    		int p = lower_bound(pol.begin(), pol.end(), pos) - pol.begin();
    		val[p] -= 1;
    	}
    	void ins(int pos, int v = 1) {
    		int l = 0, r = pol.size() - 1, p = r + 1;
    		while(l <= r) {
    			int mid = (l + r) >> 1;
    			if(pol[mid] >= pos) r = mid - 1, p = mid;
    			else l = mid + 1;
    		}
    		//int p = lower_bound(pol.begin(), pol.end(), pos) - pol.begin();
    		if(p < pol.size() && pol[p] == pos) val[p] += v;
    		else {
    			//cerr << pol.size() << ' ';
    			//int d = pol.size();
    			pol.insert(pol.begin() + p, pos); //cerr << pos << endl;
    			val.insert(val.begin() + p, v);
    			//d -= pol.size(); 
    			//assert(d == -1);
    			//assert(sz + 1 == pol.size());
    		//	cerr << d << endl;
    		//	cerr << (sz + 1) << ' ' << pol.size() << endl;
    		//	sz = pol.size();
    			sz ++; 
    			//assert(sz == pol.size());
    			//cerr << sz << ' ' << pol.size() << endl;
    		//cerr << pol.size() << endl;
    		}
    	}
    	#define mod 1000000007
    	mint query(mint v) {
    		mint ans = 0, d = 1;
    		int lst = 0;
    		for(int i = 0; i < sz; i ++) {
    			int k = pol[i] - lst;
    			mint x = v;
    			while(k) {
    				if(k & 1) d *= x;
    				x *= x; k >>= 1;
    			}
    			//d *= v ^ (pol[i] - lst);
    			ans += d * val[i];
    			lst = pol[i];
    		}
    		return ans;
    	}
    	void clear() {
    		pol.clear(); val.clear();
    	}
    } ;
    
    inline void poly_merge(const Poly &a, const Poly &b, Poly &c) {
    	static mint val[N];
    	static int pol[N];
    	int i = 0, j = 0, k = -1;
    	while(i < a.sz || j < b.sz) {
    		//assert(i < a.sz || j < b.sz);
    		if(i < a.sz && (j >= b.sz || (a.pol[i] <= b.pol[j]))) {
    			if(k < 0 || pol[k] < a.pol[i]) {
    				pol[++ k] = a.pol[i];
    				val[k] = a.val[i];
    			} 
    			else val[k] += a.val[i];
    			i ++;
    		} 
    		else {
    			if(k < 0 || pol[k] < b.pol[j]) {
    				pol[++ k] = b.pol[j];
    				val[k] = b.val[j];
    			}
    			else val[k] += b.val[j];
    			j ++;
    		}
    		//cerr <<i;
    	}
    	c.resize(k + 1);
    	for(int i = 0; i <= k; i ++) c.val[i] = val[i], c.pol[i] = pol[i];
    	//cerr << c.sz << ' ' << c.val.size() << endl;
    
    } 
    
    inline Poly operator +(const Poly &a, const Poly &b) {
    	static mint val[N];
    	static int pol[N];
    	int i = 0, j = 0, k = -1;
    	while(i < a.sz || j < b.sz) {
    		//assert(i < a.sz || j < b.sz);
    		if(i < a.sz && (j >= b.sz || (a.pol[i] <= b.pol[j]))) {
    			if(k < 0 || pol[k] < a.pol[i]) {
    				pol[++ k] = a.pol[i];
    				val[k] = a.val[i];
    			} 
    			else val[k] += a.val[i];
    			i ++;
    		} 
    		else {
    			if(k < 0 || pol[k] < b.pol[j]) {
    				pol[++ k] = b.pol[j];
    				val[k] = b.val[j];
    			}
    			else val[k] += b.val[j];
    			j ++;
    		}
    		//cerr <<i;
    	}
    	Poly c(k + 1);
    	for(int i = 0; i <= k; i ++) c.val[i] = val[i], c.pol[i] = pol[i];
    	//cerr << c.sz << ' ' << c.val.size() << endl;
    	//for(int i = 0; i <= k; i ++) {
    	//	cerr << c.pol[i] << endl;
    	//}
    	return c;
    } 
    
    #define ls(x) (x << 1)
    #define rs(x) (x << 1 | 1)
    
    int n, m;
    
    struct Node {
    	Poly sum_poly; int left_poly, right_poly;
    	mint cj, sum, left_cj, right_cj, res;
    	int midopt, left_val, right_val;
    	int val_tg, opt_tg, len;
    } t[N << 2];
    
    int val_seq[N];
    int opt_seq[N];
    
    inline Node merge(Node &Left, Node &Right, int midopt) {
    	Node Merge; //return Merge;
    	Merge.cj = Left.cj * Right.cj;
    	Merge.sum = Left.sum + Right.sum;
    	Merge.left_val = Left.left_val;
    	Merge.right_val = Right.right_val;
    	if(midopt == 0) {
    		poly_merge(Left.sum_poly, Right.sum_poly, Merge.sum_poly);
    	//	Merge.sum_poly = Left.sum_poly + Right.sum_poly;
    		Merge.left_poly = Left.left_poly;
    		Merge.right_poly = Right.right_poly;
    		Merge.left_cj = Left.left_cj;
    		Merge.right_cj = Right.right_cj;
    		Merge.res = Left.res + Right.res;
    	}
    	else {
    		poly_merge(Left.sum_poly, Right.sum_poly, Merge.sum_poly);
    		//Merge.sum_poly = Left.sum_poly + Right.sum_poly;
    		Merge.sum_poly.del(Left.right_poly);
    		Merge.sum_poly.del(Right.left_poly);
    		Merge.sum_poly.ins(Left.right_poly + Right.left_poly, 1);
    		Merge.left_poly = (Left.left_poly == Left.len ? Left.len + Right.left_poly : Left.left_poly);
    		Merge.right_poly = (Right.right_poly == Right.len ? Right.len + Left.right_poly : Right.right_poly);
    		Merge.res = (Left.res - Left.right_cj) + (Right.res - Right.left_cj);
    		Merge.res += Left.right_cj * Right.left_cj;
    		Merge.left_cj = (Left.left_poly == Left.len ? Left.cj * Right.left_cj : Left.left_cj);
    		Merge.right_cj = (Right.right_poly == Right.len ? Right.cj * Left.right_cj : Right.right_cj);
    	}
    	return Merge;
    }
    
    void update(int x) {
    	/*
    		int midopt, left_val, right_val;
    		int val_tg, opt_tg, len;
    
    	*/
    	int midopt = t[x].midopt;
    	int val_tg = t[x].val_tg;
    	int opt_tg = t[x].opt_tg;
    	int len = t[x].len;
    	t[x] = merge(t[ls(x)], t[rs(x)], midopt);
    	t[x].midopt = midopt;
    	t[x].val_tg = val_tg;
    	t[x].opt_tg = opt_tg;
    	t[x].len = len;
    	//cerr << x << ' ' << t[x].res << endl;
    }
    
    void pushdown_val(int x, mint v) {
    	t[x].val_tg = v;
    	//cerr << t[x].left_poly << endl;
    	//cerr << t[x].right_poly << endl;
    	//cerr << t[x].len << endl;
    	t[x].left_cj = v ^ t[x].left_poly;
    	t[x].right_cj = v ^ t[x].right_poly;
    	t[x].cj = v ^ t[x].len;
    	t[x].sum = v * t[x].len;
    	//cerr << t[x].left_poly << endl;
    	//cerr << t[x].right_poly << endl;
    	//cerr << v << endl;
    	t[x].res = t[x].sum_poly.query(v);
    	//cerr << t[x].res << endl;
    	t[x].left_val = v;
    	t[x].right_val = v;
    }
    
    void pushdown_opt(int x, int opt) { //cerr << x << endl;
    	if(t[x].len == 1) return ;
    	t[x].opt_tg = opt;
    	t[x].midopt = opt;
    	if(opt == 0) {
    		t[x].sum_poly.clear();
    		t[x].sum_poly.sz = 0;
    		t[x].sum_poly.ins(1, t[x].len);
    		t[x].left_poly = t[x].right_poly = 1;
    		t[x].res = t[x].sum;
    		t[x].left_cj = t[x].left_val;
    		t[x].right_cj = t[x].right_val;
    	}
    	else {
    		t[x].sum_poly.clear(); //cerr << t[x].sum_poly.val.size() << endl;
    		t[x].sum_poly.sz = 0;
    		t[x].sum_poly.ins(t[x].len, 1);
    		//cerr << t[x].sum_poly.val.size() << endl;
    		t[x].left_poly = t[x].right_poly = t[x].len;
    		t[x].res = t[x].cj;
    		t[x].left_cj = t[x].cj;
    		t[x].right_cj = t[x].cj;
    	}
    }
    
    void pushdown(int x) {
    	if(t[x].opt_tg != -1) {
    		pushdown_opt(ls(x), t[x].opt_tg);
    		pushdown_opt(rs(x), t[x].opt_tg);
    		t[x].opt_tg = -1;
    	}
    	if(t[x].val_tg != 0) {
    		pushdown_val(ls(x), t[x].val_tg);
    		pushdown_val(rs(x), t[x].val_tg);
    		t[x].val_tg = 0;
    	}
    }
    
    void build(int x, int l, int r) { //cerr << x << ' ' << l << ' ' << r << endl;
    	t[x].val_tg = 0;
    	t[x].opt_tg = -1;
    	t[x].len = r - l + 1;
    //	cerr << x << ' ' << l << ' ' << r << endl;
    //	cerr << x << ' ' << t[x].opt_tg << endl;
    	if(l == r) {
    		Poly tmp(1);
    		tmp.pol[0] = 1;
    		tmp.val[0] = 1;
    		t[x].sum_poly = tmp;
    		t[x].left_poly = t[x].right_poly = 1;
    		t[x].cj = t[x].sum = t[x].left_cj = t[x].right_cj = t[x].res = val_seq[l];
    		t[x].left_val = val_seq[l];
    		t[x].right_val = val_seq[l];
    		//cerr << x << ' ' << l << ' ' << r << ' ' << t[x].res << endl;
    		return ;
    	}
    	int mid = (l + r) >> 1;
    	t[x].midopt = opt_seq[mid];
    	//cerr << mid << endl;
    	//if(x == 4) cerr << opt_seq[mid] << endl;
    	build(ls(x), l, mid); build(rs(x), mid + 1, r);
    	update(x);
    //	cerr << x << ' ' << l << ' ' << r << ' ' << t[x].res << ' ' << t[x].midopt << endl;
    }
    
    void Modify_Val(int x, int l, int r, int L, int R, int val) { //cerr << x << endl;
    	
    	if(L <= l && r <= R) {
    		pushdown_val(x, val); return ;
    	}
    	//cerr << t[x].opt_tg << endl;
    	pushdown(x); //cerr << l << ' ' << r << ' ' << L << ' ' << R << endl;
    	int mid = (l + r) >> 1;
    	if(L <= mid) Modify_Val(ls(x), l, mid, L, R, val);
    	if(R > mid) Modify_Val(rs(x), mid + 1, r, L, R, val);
    	update(x);
    }
    
    void Modify_Opt(int x, int l, int r, int L, int R, int opt) {
    	if(r - l + 1 <= 1) return ;
    	if(L <= l && r <= R) {
    		//cerr << x << ' ' << l << ' ' << r << endl;
    		pushdown_opt(x, opt); return ;
    	}
    	pushdown(x);
    	int mid = (l + r) >> 1;
    	if(L <= mid && R >= mid) t[x].midopt = opt;
    	if(L <= mid) Modify_Opt(ls(x), l, mid, L, R, opt);
    	if(R > mid) Modify_Opt(rs(x), mid + 1, r, L, R, opt);
    	update(x);
    }
    
    Node Query(int x, int l, int r, int L, int R) { //cerr << x << endl;
    	if(L <= l && r <= R) return t[x];
    	pushdown(x);
    	int mid = (l + r) >> 1;
    	if(L > mid) return Query(rs(x), mid + 1, r, L, R);
    	if(R <= mid) return Query(ls(x), l, mid, L, R);
    	Node lps, rps;
    	lps = Query(ls(x), l, mid, L, R);
    	rps = Query(rs(x), mid + 1, r, L, R);
    //	cerr << t[x].midopt << endl;
    //	cerr << lps.res << ' ' << rps.res << endl;
    	return merge(lps, rps, t[x].midopt);
    }
    
    int main() {
    	cin >> n >> m;
    	for(int i = 1; i <= n; i ++) {
    		unsigned int v;
    		cin >> v;
    		v %= (unsigned int) (1e9 + 7);
    		val_seq[i] = v;
    		//val_seq[i] %= (int) (1e9 + 7);
    	}
    	for(int i = 1; i <  n; i ++) cin >> opt_seq[i];
    	build(1, 1, n); //return 0;
    	//cout << t[1].res << endl; return 0;
    	while(m --) {
    		int op, l, r;
    		cin >> op >> l >> r; //cerr << op << endl;
    		if(op == 1) {
    			unsigned int x; cin >> x; x %= (unsigned int) (1e9 + 7);
    			Modify_Val(1, 1, n, l, r, x);
    		}
    		if(op == 2) {
    			unsigned int x; cin >> x; x %= (unsigned int) (1e9 + 7);
    			Modify_Opt(1, 1, n, l, r, x);
    		}
    		if(op == 3) {
    			Node tmp = Query(1, 1, n, l, r);
    			cout << tmp.res << endl;
    		}
    	}
    	return 0;
    }
    
    inline int log2(unsigned int x) { return __builtin_ffs(x); }
    inline int popcount(unsigned int x) { return __builtin_popcount(x); }
    inline int popcount(unsigned long long x) { return __builtin_popcountl(x); }
    
    // Last Year
    
  • 相关阅读:
    DTD与shema学习
    xml基本语法学习
    快速写出main方法和system.out.print()
    Eclipse常见快捷键
    System.out.print()与toString()
    HttpURLConnection学习
    如何查看开关机时间
    阿里云云服务器硬盘分区及挂载
    java环境搭建
    使用jstack 发现死锁
  • 原文地址:https://www.cnblogs.com/clover4/p/15229354.html
Copyright © 2011-2022 走看看