码迷,mamicode.com
首页 > 其他好文 > 详细

十二省联考 2019

时间:2019-04-08 15:30:26      阅读:326      评论:0      收藏:0      [点我收藏+]

标签:src   hid   gif   min   priority   push   register   表示   解决   

T1

给一个序列,求前 $k$ 大区间异或和的和

$n \leq 500000,k \leq min(n^2,200000)$

sol:

超级钢琴

对每个 $i$,维护一个三元组 $(l,r,i)$ 表示左端点在 $[l,r]$,右端点在 $i$ 的区间异或最值,维护一个堆,按这个异或最值排序,每次将堆顶拿出来,分裂成最多两个区间,查一下异或最大值即可,区间异或最大值可以前缀和+可持久化 Trie 来解决

技术图片
#include <bits/stdc++.h>
#define LL long long
#define rep(i, s, t) for(register int i = (s), i##end = (t); i <= i##end; ++i)
#define dwn(i, s, t) for(register int i = (s), i##end = (t); i >= i##end; --i)
using namespace std;
inline LL read() {
    LL x = 0, f = 1; char ch = getchar();
    for(; !isdigit(ch); ch = getchar()) if(ch == -) f = -f;
    for(; isdigit(ch); ch = getchar()) x = 10 * x + ch - 0;
    return x * f;
}
const int maxn = 5e5 + 10;
int n, k; LL a[maxn];
int root[maxn], ch[maxn << 6][2], idx[maxn << 6], v[maxn << 6], ToT;
void Insert(int &x, int pre, LL val, int LG, int id) {
    x = ++ToT; ch[x][0] = ch[pre][0]; ch[x][1] = ch[pre][1]; v[x] = v[pre] + 1; idx[x] = idx[pre];
    if(LG == -1) { idx[x] = id; return; }
    int px = (val >> LG) & 1; px = px ? 1 : 0;
    Insert(ch[x][px], ch[pre][px], val, LG - 1, id);
}
int query(int x, int pre, LL val, int LG) {
    if(LG == -1) return idx[x]; int px = (val >> LG) & 1; px = px ? 1 : 0;
    if(v[ch[x][!px]] - v[ch[pre][!px]] > 0)  return query(ch[x][!px], ch[pre][!px], val, LG - 1); 
    else return query(ch[x][px], ch[pre][px], val, LG - 1);
}
struct Node {
    int l, r, mxpos, i; LL ret;
    Node() {}
    Node(int _l, int _r, int _i) {
        l = _l, r = _r, i = _i;
        mxpos = query(root[r], root[l - 1], a[i], 31);
        ret = a[i] ^ a[mxpos - 1];
    }
    bool operator < (const Node &b) const { return ret < b.ret; }
}; priority_queue<Node> q;
int main() {
//    freopen("2.in","r",stdin);
    n = read(), k = read(); rep(i, 1, n) a[i] = a[i - 1] ^ read();
    rep(i, 1, n) Insert(root[i], root[i - 1], a[i - 1], 31, i);
    rep(i, 1, n) q.push(Node(1, i, i)); LL ans = 0;
    while(k--) {
        Node cur = q.top(); q.pop(); ans += cur.ret;
        if(cur.l < cur.mxpos) q.push(Node(cur.l, cur.mxpos - 1, cur.i));
        if(cur.r > cur.mxpos) q.push(Node(cur.mxpos + 1, cur.r, cur.i));
    } cout << ans << endl;
}
View Code

 

T2

给一个字符串,给 $n_a$ 个 $A$ 类子串,$n_b$ 个 $B$ 类子串,给出 $m$ 个 $A \rightarrow B$ 的连边,存在 $A_i \rightarrow A_j$ 当且仅当存在 $B$ 使得 $A_i \rightarrow B$ 且 $B$ 是 $A_j$ 的前缀

$|S|,n_a,n_b,m \leq 2 \times 10^5$

十二省联考 2019

标签:src   hid   gif   min   priority   push   register   表示   解决   

原文地址:https://www.cnblogs.com/Kong-Ruo/p/10670357.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!