洛谷P3391【无旋treap】

什么叫tnd的优雅?这tnd的就是优雅!

普通的treap如果遇到区间序列问题就没办法了

比如这道splay的模板题,根本没法做。

但是总会有神仙让他可以做!

我们现在不需要insert和del了,因为都是针对单点维护的操作。

我们要学会区间insert和区间del!

split(int rt, int k, int &x, int &y)
将一整棵树分成两棵树,k就是划分的依据,我们可以根据需求将权值小于k的划分到一棵树,权值
大于k的划分到另外一棵树。也可以把前k个划分到一棵树,剩下的划分到另外一棵树。

具体的操作就是根据二叉排序树的特性,假设要分成x,y两棵树,约定x为的权值或序列小的一边。

如果当前节点的权值大于k(按权值划分)或者左子树的节点数大于k(按序列划分)那么当前节点肯定是属于y树的反之就是x树。这个时候我们只需要考虑x与y的左子树的关系了(结合二叉树的特性想一想为什么),反之只需要考虑x的右子树和y的关系。

merge(int A, int B)
将A,B两棵树合并成一棵树。
结合的时候要考虑到二叉树的左>中>右的特性,的话我们只有两种可能的合并方式,但是别忘了treap是有随机权的,这样可以让我们的树更一点。所以我们可以让权重大的在上。。。
如果你没听懂,推荐一个我看的博客。
可能有配图要容易理解的多。

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6+5;
typedef long long ll;
const ll mod = 1e9+7;
int Case = 1;
int n, m;
struct Random {
  int sed, A, C, M;
  Random(int sed = rand(), int A = 48271, int C = 57, int M = 2147483647)
      : sed(sed), A(A), C(C), M(M) {}
  int out() { return (sed = ((A * sed + C) % M)); }
} A;
struct Treap{
    int ch[maxn][2], val[maxn];
    int dat[maxn], size[maxn], flag[maxn];
    int root, tot;
    int newnode(int v) {
        val[++tot] = v;
        dat[tot] = A.out();
        size[tot] = 1;
        return tot;
    }
    void pushup(int rt) {
        size[rt] = 1 + size[ch[rt][0]] + size[ch[rt][1]];
    }
    void pushdown(int rt) {
        if(flag[rt]) {
            swap(ch[rt][0], ch[rt][1]);
            if(ch[rt][0]) flag[ch[rt][0]] ^= 1;
            if(ch[rt][1]) flag[ch[rt][1]] ^= 1;
            flag[rt] = 0;
        }
    }
    void split(int rt, int k, int &x, int &y) {
        if(!rt) x = y = 0;
        else {
            pushdown(rt);
            if(k <= size[ch[rt][0]]) {
                y = rt;
                split(ch[rt][0], k, x, ch[rt][0]);
            }
            else {
                x = rt;
                split(ch[rt][1], k-size[ch[rt][0]]-1, ch[rt][1], y);
            }
            pushup(rt);
        }
    }
    int merge(int A, int B) {
        if(!A || !B) return A + B;
        if(dat[A] < dat[B]) {
            pushdown(A);
            ch[A][1] = merge(ch[A][1], B);
            pushup(A);
            return A;
        }
        else {
            pushdown(B);
            ch[B][0] = merge(A, ch[B][0]);
            pushup(B);
            return B;
        }
    }
    void dfs(int rt) {
        if(!rt) return;
        pushdown(rt);
        dfs(ch[rt][0]);
        printf("%d ", val[rt]);
        dfs(ch[rt][1]);
    }
}treap;
void solve() {
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i++) {
        treap.root = treap.merge(treap.root, treap.newnode(i));
    }
    for(int i = 1; i <= m; i++) {
        int l, r, a, b, c;
        scanf("%d%d", &l, &r);
        treap.split(treap.root, l-1, a, b);
        treap.split(b, r-l+1, b, c);
        treap.flag[b] ^= 1;
        treap.root = treap.merge(a, treap.merge(b, c));
    }
    treap.dfs(treap.root);
    return;
}
int main() {
	srand(time(0));
    //g++ -std=c++11 -o2 1.cpp -o f && ./f < in.txt
    //ios::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
    //freopen("in.txt", "r", stdin);
    //freopen("out.txt","w",stdout);
#endif
while(Case--) {
    solve();
    }
return 0;
}
全部评论

相关推荐

12-22 16:31
已编辑
桂林电子科技大学 Python
很奥的前端仔:如果你接了offer 临时又说不去 hr确实要多做一些工作。 当然如果是接offer之前当我没说
点赞 评论 收藏
分享
11-07 03:09
深圳大学 C++
实习秋招做的很差,也想总结一下自己的大学生涯吧。不算太摆,但是很迷。0.大学前高考发挥超常,才来到深大计软。大学前暑期基本上都是玩游戏了。接触了python(李笑来)但是没接触到online&nbsp;judge,也没去多了解编程生态、计算机行业。背了背单词,但是没去规划指标如六级,没制定计划不了了之。1.大一军训时去了校ACM培训,当时dev编译器都不会下载。军训期间积极看B站大学c语言课程。力扣,牛客都是知道的,但是没有成为很好的跳板。第二次培训,看不懂cpp的&nbsp;cin&amp;gt;&amp;gt;,网上搜了也没搞懂,再加上周末跟训得三个多小时,感觉跟不上放弃了。自费报了蓝桥杯,混了省二跟着一些机构课程学习,走的cpp路线。暑假在linux上熟悉vim操作。2.大二朝花夕拾,又去参加ACM训练,跟了一年,寒假都在码&nbsp;带懒标记的线段树。codeforce和力扣赛都在打打(竞赛还是有趣的)。集训队入队周赛打四场,校赛拿金,面试时表现差,说自己想就业,遂挂。当时四月多,2024华为软件精英挑战赛也在打,拿了80名(前64才有三等奖)。蓝桥杯国二。很多晚上跑步来消磨时间。3.大三上修了深大最强的计算机图形学,408找实习,投简历了说自己只有周末有空,遂没在找。也没看牛客真实行情。寒假随便做了个日志器,属于混过去了。当时接到字节的面试(人生处女面),前一天觉都睡不好,很紧张,手撕做的不好,话都说不利索了。面评脏。大三下找实习,cpp选手,没有很好经历、项目,运气好去了学校附近中厂实习。4.大四现在,貌似对开发不上心?没有好的offer(甚至hot100不会做)其实同届好多同学都拿的不错。还有保研C9的。嗯,考研吧。————对自己行为的分析:a.应试教育+应试家庭教育,我的个性是固执、遵规守矩的。b.还有莫名的孤独,明明有很多朋友,但还是没有很好的内驱力,没有坚定的理想。c.自己没有很好的调研、探索和规划能力。大家也可以锐评一下😊
_Matrice_:差不多的性格,不然不会本科时硬杠cpp(那个时候还没有大模型,啃完一整本primer和习题,还是做不出来什么东西),还找不到方向,相比之下学习一些应用层的同学已经能够参考别人的方法做出实用的应用了。学东西,找实习,感觉更多地是出于和别人比较,而不是自我内驱。不过...正如deft所说,人生不需要他人的建议,所以也没有标准化的路径,在能够自食其力的背景下慢慢找到自己的生活方式吧...。另外面试很多时候看运气、眼缘
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务