一篇文章讲明白hdu4453(splay做法)

简介: 一篇文章讲明白hdu4453(splay做法)

妈呀,我裂开了啊,调了一天,终于出了

总结一下:

1:add懒标记是用+不是=!!!(如果本来就有标记的就覆盖了),反转也是,一定要注意懒标记不能=

2:splay用来进行区间操作的话,建树的时候可以像(BST)splay一样加入两个哨兵,一个代表下标0,一个代表下标n+1,写函数的时候就不用考虑边界了

3:splay可以像线段树一样进行区间操作,push_up,push_down,但是一定要注意,先push_down自己,再push_down孩子,先push_up孩子,再push_up自己!

4:二叉树建树以及加点多用引用,好处是真的多

代码:

#include

#include[span style="color: rgba(0, 0, 255, 1)">string.h>

using namespace std;

const int maxn = 2e5 + 100;

inline int read()

{

int s = 0, w = 1; char ch = getchar();

while (ch < '0' || ch > '9') { if (ch == '-') w = -1; ch = getchar(); }

while (ch >= '0' ch <= '9') s = s 10 + ch - '0', ch = getchar();

return s w;

}

#define ls(x) tree【x】【0】

#define rs(x) tree【x】【1】//良好习惯,不加的话下面用到太多了,容易出错

int tree【maxn】【2】, siz【maxn】, val【maxn】, add【maxn】, rev【maxn】, fa【maxn】;

int root, tot;

void //代码效果参考:http://www.zidongmutanji.com/bxxx/283530.html

new_node(int x, int f, int valu)//引用大法好,以后要经常用QAQ

{

x = ++tot;

fa【x】 = f;

val【x】 = valu;

siz【x】 = 1; rev【x】 = add【x】 = 0;

ls(x) = rs(x) = 0;

}

void push_up(int rt) {

siz【rt】 = siz【ls(rt)】 + siz【rs(rt)】 + 1;

}

void push_down(int rt) {

if (rev【rt】) {

swap(ls(rt), rs(rt));//传递

rev【ls(rt)】 ^= 1;

rev【rs(rt)】 ^= 1;

rev【rt】 = 0;//重置

}

if (add【rt】) {//add【rt】是关于其孩子的效果

val【rs(rt)】 += add【rt】;

val【ls(rt)】 += add【rt】;

add【ls(rt)】 += add【rt】;

add【rs(rt)】 += add【rt】;

add【rt】 = 0;//一定要记得重置

}

}

void rotate(int x) {//这里出错就没办法了,记得更新子节点同时更新子节点的父节点,两两配对

int y = fa【x】, z = fa【y】, f = (rs(y) == x);

push_down(x); push_down(y);//先自己再父亲,我淦!

tree【y】【f】 = tree【x】【f ^ 1】;

fa【tree【x】【f ^ 1】】 = y;

if (z) {

tree【z】【rs(z) == y】 = x;

}

fa【x】 = z;

tree【x】【f ^ 1】 = y;

fa【y】 = x;

push_up(y);

}

void splay(int x, int top) {

push_down(x);//每次tree下标作为参数的都push_down

while (fa【x】 != top) {

int y = fa【x】, z = fa【y】;

///先祖再父后自己????????

if (z != top) {

if ((ls(z) == y) ^ (ls(y) == x)) {

rotate(x);

}

else {

rotate(y);

}

}

rotate(x);

}

push_up(x);//可以放这里,因为每次旋转后x都是父亲节点,没必要更新,最后旋转完成来更新就行

if (top == 0)root = x;//旋转到根记得修正

}

void rotto(int k, int top) {//把排名当作其在数组中的位置,这样就能轻松完成区间操作

int p = root;

push_down(p);

while (siz【ls(p)】 != k) {//由于增加了两个点,一个最小点,一个最大点,所以查找的时候左孩子的siz就是位置

if (siz【ls(p)】 > k)p = ls(p);

else k -= (siz【ls(p)】 + 1), p = rs(p);

push_down(p);

}

splay(p, top);

}

void insert(int valu, int pos) {

rotto(pos, 0); rotto(pos + 1, root);

new_node(ls(rs(root)), rs(root), valu);

push_up(rs(root));//一般插入后需要旋转到根,但是这里我们只是插入到离根位置为2的点,距离比较近,直接更新即可,记得先更新孩子,再更新根

push_up(root);

}

void add_val(int L, int R, int x) {

rotto(L - 1, 0); rotto(R + 1, root);//把L-R区间内的数都赶到右子树的左子树上,然后给个懒标记即可

add【ls(rs(root))】 += x;//2 卧槽!!!!

val【ls(rs(root))】 += x;

}

void reverse(int L, int R) {

rotto(L - 1, 0); rotto(R + 1, root);//没有两个哨兵,你这个操作要多判断多少东西,想一想

rev【ls(rs(root))】 ^= 1;

}

void del(int pos) {

rotto(pos - 1, 0); rotto(pos + 1, root);//还是把pos位置的数赶到右子树的左子树,删除即可.

ls(rs(root)) = 0;

push_up(rs(root));

push_up(root);

}

void cut(int len, int last) {//把长度为len的区间接到最后面去

rotto(len + 1, 0); rotto(0, root);//由于增加了两个点,第一个点的位置永远为0,最后一个点的位置为n+1

int rt = rs(ls(root));//再通过将第一个数旋转到根的儿子位置,这样就能轻松将需要的前几个数赶到一棵树上,

rs(ls(root)) = 0;//删除前面len长度的数组成的树,并用rt保存根节点位置

push_up(ls(root));

push_up(root);

rotto(last - len, 0);//最后一个点在右侧,把刚拆出来的树区间rt加入到右边去,刚好就是旋转过来的样子

ls(rs(root)) = rt;

push_up(rs(root));

push_up(root);//记得及时更新

}

int a【maxn】;

void build(int l, int r, int rt, int fa) {//引用大法好

if (l > r) { return; }

int mid = (l + r) ] 1;

new_node(rt, fa, a【mid】);

build(l, mid - 1, ls(rt), rt);//虽然和线段树很像,但是只有n个节点,所以减一啊!!!!

build(mid + 1, r, rs(rt), rt);

push_up(rt);

}

void init(int n) {

for (int i = 1; i <= n; i++) {

a【i】 = read();

}

ls(0) = rs(0) = fa【0】 = siz【0】 = val【0】 = rev【0】 = add【0】 = 0;

root = tot = 0;//初始化注意!!!

new_node(root, 0, 0);

new_node(rs(root), root, 0);//先开两个点,用来切区间的时候方便处理,一个是左区间端点,一个是友区间端点

//就是哨兵,只不过这里面为了区间操作是按照位置排序的,而常规的splay是按照权值排序的BST树,二者作用不同.

build(1, n, ls(rs(root)), rs(root));

//这种方式建成的树的中序遍历结果就是1-n,所以叫中序建树(自己起的)

push_up(rs(root));

push_up(root);

}

int main() {

//freopen("test.txt", "r", stdin);

int now, num = 1;

int n, m, k1, k2;

while (~scanf("%d%d%d%d", n, m, k1, k2)) {

if (n == 0 m == 0 k1 == 0 k2 == 0)break;

now = 1;

init(n);

printf("Case #%d:\n", num++);

while (m--) {

string t; cin ] t;

char c = t【0】;

if (c == 'a') {

int x = read(), s = now + k2 - 1;

if (s <= n) {

add_val(now, s, x);

}

else {

add_val(now, n, x);//如果超界了就两边加上就好了

add_val(1, s - n, x);

}

}

else if (c == 'r') {

int R = now + k1 - 1;

if (R <= n) {

reverse(now, R);

}

else {

cut(R - n, n);

now = n - k1 + 1;

reverse(now, n);

}

}

else if (c == 'i') {

int x = read();

insert(x, now);

n++;

}

else if (c == 'd') {

del(now);

if (now == n)now = 1;

n--;

}

else if (c == 'm') {

int x = read();

if (x == 1)now--;

else now++;

if (now == 0)now = n;

if (now == n + 1)now = 1;

}

else if (c == 'q') {

rotto(now, 0);

printf("%d\n", val【root】);

//代码效果参考:http://www.zidongmutanji.com/bxxx/28768.html

}

}

}

return 0;

}

相关文章
|
4天前
|
存储 弹性计算 缓存
阿里云服务器租赁费用:新版租赁收费标准及活动报价参考
本文更新了2026年阿里云全系列云服务器租赁活动报价,所有特惠资源均可前往阿里云活动中心选购,整体覆盖从个人入门到企业级高性能场景的全梯度需求。其中轻量应用服务器主打极致性价比,2核2G峰值200M带宽配置每日10点、15点限时抢购价仅38元/年,2核4G配置379元/年起;高性价比的经济型e实例、通用算力型u2i实例覆盖2核4G至4核32G全档位,适配开发测试与中小型企业业务;搭载英特尔至强6处理器的第九代c9i企业级实例算力较上代提升20%,支撑高并发生产环境,不同实例规格价差清晰,用户可根据自身业务负载与预算灵活选型。
1522 110
|
11天前
|
云安全 人工智能 运维
阿里云联动百位企业安全专家,共识Agent防御最佳实践
当Agent成为新员工,你的安全边界在哪里?
1936 8
阿里云联动百位企业安全专家,共识Agent防御最佳实践
|
5天前
|
人工智能 程序员 API
Codex 接入 DeepSeek-V4-Flash:还能补上识图,提供两套方案
Codex 接入 DeepSeek-V4-Flash 怎么配?本文覆盖 CLI 与桌面端,再用 qwen3-vl-flash 补识图,两套方案可直接照做
|
5天前
|
编解码 人工智能 安全
2核4G/4核8G/8核16G阿里云服务器如何选择实例?经济型e、通用算力型u2i与计算型c9i选哪个?
本文介绍了阿里云2核4G、4核8G、8核16G三档主流配置下经济型e、通用算力型u2i和计算型c9i三种实例的最新活动价格与适用场景。同配置下三者价差显著,以2核4G为例,经济型e低至599.93元/年,计算型c9i则高达1742.08元/年。文章详细解析了各实例的性能定位:经济型e适合轻负载入门场景,u2i兼顾稳定算力与性价比,c9i凭借第9代至强处理器与芯片级安全能力支撑高性能业务。同时提示用户可叠加满减优惠券享受折上折,建议根据业务负载与预算综合决策。
522 112
|
9天前
|
存储 人工智能 关系型数据库
阿里云AI产品与云产品最新组合套餐:Token Plan、AI coding及云服务器和建站等组合优惠价
阿里云推出全新“算力+模型+应用”一站式云与AI组合套餐活动,覆盖从个人开发者到中大型企业的全场景需求。核心亮点为分三档定价的Token Plan订阅服务,支持Qwen3.8-Max-Preview大模型调用,错峰时段最低可享0.2折优惠。活动同步推出AI Coding、智能体部署、云电脑托管、0代码建站等十余类场景化组合,搭配99元/年的普惠云服务器、88元/年的入门数据库等经典特惠产品,还为企业提供1V1定制化AI转型方案,大幅降低了不同用户群体拥抱AI的技术门槛与采购成本。
713 111
|
17天前
|
人工智能 前端开发 Linux
Codex 桌面版安装 + CC Switch 接入第三方 API 完整教程(2026 最新)
2026最新教程:手把手教你安装Codex桌面版,通过CC Switch v3.17.0一键接入Fenno等国产API(兼容OpenAI Responses格式),跳过账号登录,完整启用代码审查、多步任务与上下文感知功能。零基础友好,全程图文实操。(239字)
2362 3
|
19天前
|
人工智能 JSON 安全
Fastjson远程代码执行漏洞,阿里云AI安全为您保驾护航
阿里云AI安全产品联动防御Fastjson攻击
2619 13
Fastjson远程代码执行漏洞,阿里云AI安全为您保驾护航
|
6天前
Qoder 一周年 × Qwen3.8-Max 正式上线,多重好礼限时领
8月3日,Qwen3.8-Max 正式上线Qoder,迎来Qoder一周年。新老用户可领800次免费调用,下单再赠2000次;夜间(22:00–08:00)调用5折;邀请好友双方得积分与调用额度。
392 0
|
5天前
|
人工智能 JSON Shell
2026AI漫剧本地全开源方案(附各个软件模型链接),8G显卡也能流畅运行
这是一套完全本地化部署的AI漫剧生成技术链路:涵盖LLM剧本分镜生成、FLUX文生图(IP-Adapter人脸锁定)、StoryDiffusion时序连贯控制、LTX-2.3唇形同步视频生成,及ComfyUI全流程调度。零云端费用,仅耗硬件算力,单集2–4小时可产出竖屏短视频,适配抖音/B站分发。