P5524 [Ynoi2012] NOIP2015 充满了希望 Solution

Description

有一序列 aaa,长度为 nnn
还有一个长度为 mmm 的操作序列 bbb,每个操作形如:

  • swap⁡(x,y)\operatorname{swap}(x,y)swap(x,y):交换 axa_xaxaya_yay.
  • assign⁡(l,r,k)\operatorname{assign}(l,r,k)assign(l,r,k):对每个 i∈[l,r]i \in [l,r]i[l,r] 执行 ai←ka_i \gets kaik.
  • get⁡(p)\operatorname{get}(p)get(p):求 apa_pap 的值.

现在有 qqq 个查询,每次给定一个二元组 (L,R)(L,R)(L,R),执行下面操作:

  • aaa 每一项设为 000.
  • 执行操作 bL,bL+1,⋯ ,bRb_L,b_{L+1},\cdots,b_RbL,bL+1,,bR.
  • 输出所有 get⁡\operatorname{get}get 操作的答案之和.

Limitations

1≤n,m,q≤1061 \le n,m,q \le 10^61n,m,q106
1≤k≤1091 \le k \le 10^91k109
1≤x,y≤n1 \le x,y \le n1x,yn
1≤l≤r≤n1 \le l \le r \le n1lrn
1≤L≤R≤m1 \le L \le R \le m1LRm
1s,512MB1\text{s},512\text{MB}1s,512MB

Solution

使用线段树维护区间最后一次 assign⁡\operatorname{assign}assign 的时刻,遇到 get⁡\operatorname{get}get 时,查询 ppp 点的值并记为 tit_iti.

考虑将询问挂在 rrr 上做扫描线,遇到 get⁡\operatorname{get}get 时,在 tit_iti 位置加上第 tit_iti 次操作的 kkk,对每个询问查询 [l,r][l,r][l,r] 的和,可以用树状数组.

然后卡卡常数,需要用快读.

Code

4.52KB,4.07s,119.21MB  (in total, C++ 20 with O2)4.52\text{KB},4.07\text{s},119.21\text{MB}\;\texttt{(in total, C++ 20 with O2)}4.52KB,4.07s,119.21MB(in total, C++ 20 with O2)
模板已删.

// Problem: P5524 [Ynoi2012] NOIP2015 充满了希望
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P5524
// Memory Limit: 512 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
using namespace std;

using i64 = long long;
using ui64 = unsigned long long;
using i128 = __int128;
using ui128 = unsigned __int128;
using f4 = float;
using f8 = double;
using f16 = long double;

template<class T>
bool chmax(T &a, const T &b){
	if(a < b){ a = b; return true; }
	return false;
}

template<class T>
bool chmin(T &a, const T &b){
	if(a > b){ a = b; return true; }
	return false;
}

namespace fastio {}
using fastio::read;
using fastio::write;

inline int lowbit(int x) {
	return x & -x;
}

template<class T>
struct fenwick {};

inline int ls(int u) { return 2 * u + 1; }
inline int rs(int u) { return 2 * u + 2; }

struct SegTree {
    struct Node {
        int l, r, tag;
    };
    vector<Node> tr;
    
    inline SegTree() {}
    inline SegTree(int n) {
        tr.resize(n << 2);
        build(0, 0, n - 1);
    }
    
    inline void pushdown(int u) {
        if (tr[u].tag != -1) {
            tr[ls(u)].tag = tr[rs(u)].tag = tr[u].tag;
            tr[u].tag = -1;
        }
    }
    
    inline void build(int u, int l, int r) {
        tr[u].l = l;
        tr[u].r = r;
        tr[u].tag = -1;
        if (l == r) return;
        
        const int mid = (l + r) >> 1;
        build(ls(u), l, mid);
        build(rs(u), mid + 1, r);
    }
    
    inline void assign(int u, int l, int r, int x) {
        if (l <= tr[u].l && tr[u].r <= r) {
            tr[u].tag = x;
            return;
        }
        const int mid = (tr[u].l + tr[u].r) >> 1;
        pushdown(u);
        if (l <= mid) assign(ls(u), l, r, x);
        if (r > mid) assign(rs(u), l, r, x);
    }
    
    inline int get(int u, int p) {
        if (tr[u].l == tr[u].r || tr[u].tag != -1) return tr[u].tag;
        const int mid = (tr[u].l + tr[u].r) >> 1;
        if (p <= mid) return get(ls(u), p);
        else return get(rs(u), p);
    }
};

signed main() {
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	
	const int n = read<int>(), m = read<int>(), q = read<int>();
	vector<int> op(m), x(m), y(m), val(m);
	SegTree sgt(n);
	
	for (int i = 0; i < m; i++) {
	    op[i] = read<int>();
	    if (op[i] == 1) {
	        x[i] = read<int>(), y[i] = read<int>();
	        x[i]--, y[i]--;
	        
	        int a = sgt.get(0, x[i]), b = sgt.get(0, y[i]);
	        sgt.assign(0, x[i], x[i], b);
	        sgt.assign(0, y[i], y[i], a);
	    }
	    else if (op[i] == 2) {
	        x[i] = read<int>(), y[i] = read<int>(), val[i] = read<int>();
	        x[i]--, y[i]--;
	        sgt.assign(0, x[i], y[i], i);
	    }
	    else {
	        x[i] = read<int>(), x[i]--;
	        y[i] = sgt.get(0, x[i]);
	    }
	}
	
	fenwick<i64> fwk(m);
	vector<vector<pair<int, int>>> queries(m);
	vector<i64> ans(q);
	for (int i = 0, l, r; i < q; i++) {
	    l = read<int>(), r = read<int>();
	    l--, r--;
	    queries[r].emplace_back(l, i);
	}
	
	for (int i = 0; i < m; i++) {
	    if (op[i] == 3 && y[i] != -1) fwk.add(y[i], val[y[i]]);
	    for (auto [pos, id] : queries[i]) ans[id] = fwk.ask(pos, i);
	}
	
	for (const auto& i : ans) {
	    write(i);
	    putchar_unlocked('\n');
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值