zoukankan      html  css  js  c++  java
  • HNOI2017影魔

    (HNOI2017影魔)

    • 首先有(p1)贡献的区间能发现只有(O(n))个, 具体地,将数字从大到小插入区间,只有这个数的((位置的))前驱后继才有贡献,所以第一部分将询问放在右端点,扫描线就能做
    • 对于有(p2)贡献的区间,考虑枚举中间最大的数,即求出(L[i], R[i]),表示左边右边第一个大于它的位置,
      • 具体地只考虑第一种情况即(a[l] < a[mid] < a[r]),第二种情况类似,发现只有(lin(L[i],i), r = R[i])的区间有贡献,把这些区间都存在右端点, 最后一起取并,直接同上的扫描线做一遍
    • 代码写的有点长, 但好歹能过?
    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define SZ(x) ((int) ((x).size()))
    #define fst first
    #define snd second
    
    typedef pair<int, int> pii;
    typedef long long ll;
    
    inline int read(int x = 0, int _f = 0)
    {
    	char c = getchar();
    	for (; !isdigit(c); c = getchar()) 
    		_f |= (c == '-');
    	for (;  isdigit(c); c = getchar()) 
    		x = x*10 + c-'0';
    	return _f? -x : x;
    }
    template <typename T> bool chkmax(T &a, T b) 
    {
    	return a < b? a = b, true : false; 
    }
    template <typename T> bool chkmin(T &a, T b) 
    {
    	return a > b? a = b, true : false; 
    }
    
    const int N = 2e5 + 5;
    
    int n, q, p1, p2;
    
    int A[N], P[N];
    
    struct Query
    {
    	int l, r, id;
    	Query(int l = 0, int r = 0, int id = 0) : l(l), r(r), id(id) {}
    }qry[N];
    
    vector<pii> deal[N], arr[N];
    
    ll ans[N];
    
    int R[N], L[N];
    
    struct SegmentTree
    {
    #define mid ((l + r) >> 1)
    #define lc (h << 1)
    #define rc (lc | 1)
    
    ll sum[N << 2], addv[N << 2];
    
    inline void clear(int n)
    {
    	for (int i = 1; i <= n << 2; ++i) {
    		sum[i] = addv[i] = 0;
    	}
    }
    
    inline void push_down(int h, int l, int r)
    {
    	if (addv[h]) {
    		sum[lc] += addv[h] * (mid - l + 1), addv[lc] += addv[h];
    		sum[rc] += addv[h] * (r - mid), addv[rc] += addv[h];
    		addv[h] = 0;
    	}
    }
    
    void modify(int h, int l, int r, int ql, int qr)
    {
    	if (ql <= l && r <= qr) {
    		sum[h] += r - l + 1; addv[h] ++;
    		return ;
    	}
    
    	push_down(h, l, r);
    
    	if (ql <= mid) modify(lc, l, mid, ql, qr);
    	if (qr > mid) modify(rc, mid + 1, r, ql, qr);
    
    	sum[h] = sum[lc] + sum[rc];
    }
    
    ll query(int h, int l, int r, int ql, int qr)
    {
    	if (qr < ql) return 0;
    
    	if (ql <= l && r <= qr) return sum[h];
    	push_down(h, l, r);
    	return (ql <= mid? query(lc, l, mid, ql, qr) : 0) +
    		(qr > mid? query(rc, mid + 1, r, ql, qr) : 0);
    }
    
    #undef lc
    #undef rc
    #undef mid
    }SEGT1, SEGT2;
    
    void combine(vector<pii> &A)
    {
    	vector<pii> tmp = A; A.clear();
    	sort(tmp.begin(), tmp.end());
    
    	int l = 0, r = -1;
    	for (int j = 0; j < SZ(tmp); ++j) {
    		if (j && tmp[j].fst <= r) {
    			chkmax(r, tmp[j].snd);
    		}
    		else {
    			if (l <= r) A.push_back(pii(l, r));
    			l = tmp[j].fst;
    			r = tmp[j].snd;
    		}
    	}
    	if (l <= r) A.push_back(pii(l, r));
    }
    
    void exec()
    {
    	set<int> pos;
    
    	for (int i = n; i >= 1; --i) {
    		auto it = pos.insert(P[i]).fst;
    
    		if (it != pos.begin()) {
    			deal[*it].push_back(pii(*prev(it), 1));
    //			printf("[%d, %d]
    ", *prev(it), *it);
    			L[P[i]] = *prev(it);
    		}
    		if (it != --pos.end()) {
    			deal[*next(it)].push_back(pii(*it, 1));
    //			printf("[%d, %d]
    ", *it, *next(it));
    			R[P[i]] = *next(it);
    		}
    	}
    
    	for (int i = 1; i <= q; ++i) {
    		deal[qry[i].r].push_back(pii(i, 0));
    	}
    
    	for (int i = 1; i <= n; ++i) if (R[i]) {
    		if (L[i] + 1 < i) arr[R[i]].push_back(pii(L[i] + 1, i - 1));
    	}
    
    	for (int i = 1; i <= n; ++i) combine(arr[i]);
    
    	for (int i = 1; i <= n; ++i) {
    		for (int j = 0; j < SZ(arr[i]); ++j) {
    			SEGT2.modify(1, 1, n, arr[i][j].fst, arr[i][j].snd);
    		}
    		for (int j = 0; j < SZ(deal[i]); ++j) {
    			if (!deal[i][j].snd) {
    				int o = deal[i][j].fst;
    				ans[qry[o].id] += SEGT2.query(1, 1, n, qry[o].l, qry[o].r-1) * p2;
    				ans[qry[o].id] += SEGT1.query(1, 1, n, qry[o].l, qry[o].r-1) * p1;
    			}
    			else {
    				SEGT1.modify(1, 1, n, deal[i][j].fst, deal[i][j].fst);
    			}
    		}
    	}
    }
    
    void repeatP2()
    {
    	SEGT2.clear(n);
    	for (int i = 1; i <= n; ++i) arr[i].clear(), deal[i].clear();
    
    	for (int i = 1; i <= q; ++i) {
    		deal[qry[i].l].push_back(pii(i, 0));
    	}
    
    	for (int i = 1; i <= n; ++i) if (L[i]) {
    		if (i + 1 < R[i]) {
    			arr[L[i]].push_back(pii(i + 1, R[i] - 1));
    		}
    	}
    
    	for (int i = 1; i <= n; ++i) combine(arr[i]);
    
    	for (int i = n; i >= 1; --i) {
    		for (int j = 0; j < SZ(arr[i]); ++j) {
    			SEGT2.modify(1, 1, n, arr[i][j].fst, arr[i][j].snd);
    		}
    		for (int j = 0; j < SZ(deal[i]); ++j) {
    			int o = deal[i][j].fst;
    			ans[qry[o].id] += SEGT2.query(1, 1, n, qry[o].l+1, qry[o].r) * p2;
    		}
    	}
    }
    
    int main()
    {
    	freopen("sf.in", "r", stdin);
    	freopen("sf.out", "w", stdout);
    
    	n = read(), q = read(); p1 = read(), p2 = read();
    
    	for (int i = 1; i <= n; ++i) {
    		A[i] = read();
    		P[A[i]] = i;
    		L[i] = 0, R[i] = n + 1;
    	}
    
    	for (int i = 1; i <= q; ++i) {
    		int l = read(), r = read();
    		qry[i] = Query(l, r, i);
    	}
    
    	exec(); 
    	repeatP2();
    
    	for (int i = 1; i <= q; ++i) {
    		printf("%lld
    ", ans[i]);
    	}
    
    	return 0;
    }
    
    
  • 相关阅读:
    数据库字段太多,批量快速建立实体类方法(适合大量字段建立实体类)
    SQL service 中的 ”输入SQL命令窗口“ 打开了 “属性界面” 回到 ”输入SQL命令窗口“
    计算机软件编程英语词汇集锦
    编程常用英语词汇
    svn上传和下载项目
    当启动tomcat时出现tomcat setting should be set in tomcat preference page
    Implicit super constructor Object() is undefined for default constructor. Must define an explicit constructor
    eclipse中选中一个单词 其他相同的也被选中 怎么设置
    Spring Boot的@SpringBootApplication无法引入的问题
    最全的SpringCloud视频教程
  • 原文地址:https://www.cnblogs.com/pbvrvnq/p/8672872.html
Copyright © 2011-2022 走看看