作者的题解:

如果一段操作被执行,会对整个栈有什么影响呢?

把栈弹出若干个数后再插入若干个数。

线段树:

每个点纪录三个值:执行完这段操作后会删多少个,再插多少个,插的和一共是多少。

合并值时再用一个函数查找左孩子被从右删除若干个后剩下的插入总和是多少。

建树复杂度O( N log N ), 单次查询复杂度O( log ^ 2 N), 总复杂度O( N log N + Q log ^2 N ).

树袋熊学长的题解:

• 实际上,每个加数和删除的操作可以看作是入栈和弹栈操作,之后可以用线段树维护多个操作间的关系。线段树的下标是操作时间,由于我们想得到整个序列经过修改操作后的结果,因此线段
树上维护四个信息:
s:区间内加数总和(仅考虑区间内部影响);

nd:当前区间向前删除数字的数量;
na:当前区间内“净”加的元素数。
sd:当前区间被右兄弟删除后的总和。 ※仅对左儿子维护此信息。
• 我们通过维护以上四个标记,就可以得到答案(root->s)。现在我们考虑如何维护信息。

首先,在建树或修改时,只需要将叶子节点的前三个标记维护好即可;在递归返回时,再计算最后一个。如果左儿子不够右儿子删,那么非常简单,直接利用这几个标记计算即可,l->sd=0。
比较麻烦的是左儿子不被删光的情况。我们先实现一个函数cal(x),利用sd标记计算在当前区间中删去x个元素后的和

• 有了这个函数,我们就可以非常方便地计算左儿子的sd,维护其
他标记了,不再赘述。

由于这个奇怪的函数在每层节点都会调用,而一共有O(logn)层节点,所以线段树操作的时间复杂度变为O(log 2 n),总时间复杂度也比常规的线段树多一个log。
• 难点主要在于使用额外的函数维护信息,并正确的讨论各种情况。
• 考试时一定要想清楚,时间复杂度是靠“链状”延伸的维护函数保障的,如果不小心写成了两边都下去,就变成O(n 2 )了。

还是说我自己咋写的吧,

用线段树维护操作(好象是第二次碰到这种题),对于线段树的每个节点,维护三个信息,del当前节点删除其左兄弟几个元素,add只考虑当前区间影响区间内的元素个数,val只考虑当前区间影响区间内的和。

建树时对于叶子节点就很容易了,直接赋值就行了。下面考虑怎么合并,分三种情况:

  1. add(ls(x))==del(rs(x)),相当于x节点的右儿子正好删掉了左儿子的所有元素,于是 del(x)=del(ls(x)),add(x)=add(rs(x)),val(x)=val(rs(x);
  2. add(ls(x))< del(rs(x)),x节点的右儿子删掉了左儿子的所有元素还要多,于是del(x)=dal(ls(x))+del(rs(x))-add(ls(x)),add(x)=add(rs(x)),val(x)=val(rs(x));
  3. add(ls(x))> del(rs(x)),x节点的有儿子没有全部删掉左儿子的所有元素,于是 del(x)=del(ls(x));add(x)=add(rs(x))+add(ls(x))-del(rs(x));val(x)=val(rs(x))+cal(ls(x),del(rs(x)));

cal(k,x)表示k节点的区间删掉结尾x个元素后的和:

int cal(int k,int x)
{
if(x==add(rs(k)))return val(k)-val(rs(k));
if(x<add(rs(k))) return val(k)-val(rs(k))+cal(rs(k),x);
if(x>add(rs(k))) return cal(ls(k),x-add(rs(k))+del(rs(k)));
}

到这里大概就没什么了。

最后答案为val(1),对于每次修改直接递归到对应叶子节点即可。

 #include<iostream>
#include<cstdio>
#define MAXN 200100
#define LL long long
using namespace std;
struct tree
{
int l,r,del,add,val;
#define l(x) tr[x].l
#define r(x) tr[x].r
#define del(x) tr[x].del
#define add(x) tr[x].add
#define val(x) tr[x].val
#define ls(x) (x<<1)
#define rs(x) (ls(x)+1)
}tr[MAXN*];
int m,q,k[MAXN],v[MAXN];
int cal(int k,int x)
{
if(x==add(rs(k)))return val(k)-val(rs(k));
if(x<add(rs(k))) return val(k)-val(rs(k))+cal(rs(k),x);
if(x>add(rs(k))) return cal(ls(k),x-add(rs(k))+del(rs(k)));
}
void updata(int x)
{
if(add(ls(x))==del(rs(x)))
{
del(x)=del(ls(x));add(x)=add(rs(x));val(x)=val(rs(x));
}
if(add(ls(x))<del(rs(x)))
{
del(x)=del(ls(x))+del(rs(x))-add(ls(x));
add(x)=add(rs(x));
val(x)=val(rs(x));
}
if(add(ls(x))>del(rs(x)))
{
del(x)=del(ls(x));
add(x)=add(rs(x))+add(ls(x))-del(rs(x));
val(x)=val(rs(x))+cal(ls(x),del(rs(x)));
}
}
void build(int x,int l,int r)
{
l(x)=l,r(x)=r;
if(l==r)
{
if(k[l]==) del(x)=,val(x)=v[l],add(x)=;
else del(x)=v[l],val(x)=,add(x)=;
return;
}
int mid=(l+r)>>;
build(ls(x),l,mid);
build(rs(x),mid+,r);
updata(x);
}
void change(int x,int t,int k,int v)
{
if(l(x)==r(x))
{
if(k==)del(x)=,val(x)=v,add(x)=;
else del(x)=v,val(x)=,add(x)=;
return;
}
int mid=(l(x)+r(x))>>;
if(t<=mid)change(ls(x),t,k,v);
else change(rs(x),t,k,v);
updata(x);
}
signed main()
{
/// freopen("weed.in","r",stdin); cin>>m>>q;
for(int i=;i<=m;i++)
cin>>k[i]>>v[i];
build(,,m);
int c,kk,vv;
for(int i=;i<=q;i++)
{
cin>>c>>kk>>vv;
change(,c,kk,vv);
cout<<val()<<endl;
}
}

HZOJ Weed的更多相关文章

  1. 【Foreign】Weed [线段树]

    Weed Time Limit: 20 Sec  Memory Limit: 512 MB Description 从前有个栈,一开始是空的. 你写下了 m 个操作,每个操作形如 k v : 若 k ...

  2. 【BZOJ 2957】楼房重建&&Codechef COT5 Count on a Treap&&【NOIP模拟赛】Weed 线段树的分治维护

    线段树是一种作用于静态区间上的数据结构,可以高效查询连续区间和单点,类似于一种静态的分治.他最迷人的地方在于“lazy标记”,对于lazy标记一般随我们从父区间进入子区间而下传,最终给到叶子节点,但还 ...

  3. 8.10 NOIP模拟测试16 Blue+Weed+Drink

    T1 Blue 贪心,每次跳得时候跳能跳到的最远的地方,跳过的就把他设为0,每次二分找到位置,一直跳就行,如果能跳到的位置就是当前位置或比当前位置还小(数组里现在呆着的这一块石头,二分得到的就是当前位 ...

  4. 联赛模拟测试20 C. Weed

    题目描述 \(duyege\) 的电脑上面已经长草了,经过辨认上面有金坷垃的痕迹. 为了查出真相,\(duyege\) 准备修好电脑之后再进行一次金坷垃的模拟实验. 电脑上面有若干层金坷垃,每次只能在 ...

  5. NOIP模拟测试16「Drink·blue·weed」

    话说这次考试 Drink 非常棒的一道卡常练习题,适合练习卡常 真的很棒 前置卡常知识 1.char要比int快 char是最快的 输出putchar,输入getchar 在这个题快了7000豪 2. ...

  6. ABC 203 F - Weed (DP)

    ABC203F - Weed 题意转述 S t e v e \rm Steve Steve 和 A l e x \rm Alex Alex 正在下界( N e t h e r l e n d \rm ...

  7. hzoj 2301(莫比乌斯反演)

    题意 对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd(x,y)函数为x和y的最大公 数. 思路: 与先前的那个相比,这次a,c并不一定 ...

  8. HZOJ 单

    两个子任务真的是坑……考试的时候想到了60分的算法,然而只拿到了20分(各种沙雕错,没救了……). 算法1: 对于测试点1,直接n遍dfs即可求出答案,复杂度O(n^2),然而还是有好多同学跑LCA/ ...

  9. Weed:线段树

    观察复杂度,是log级别以下回答询问的. O(1)?逗我kx呢? 自然而然地想到线段树. 学长讲的原题啊考场上还不会打. 线段树上的每个节点都表示一个操作区间. 线段树上维护的权值有3个:这个子区间一 ...

随机推荐

  1. iview 小问题笔记

    总结一下用 iview 组件期间遇到的小问题.一边做项目一边做笔记. 官方文档:iview API 按需引入: 1,iview 分页组件 <Page :total="aboutPage ...

  2. 因子分析spss怎么做 spss因子分析教程及结果解释

    因子分析spss怎么做 spss因子分析教程及结果解释 因子分析spss可以简化数据结构,将具有错综复杂关系的变量综合为数据较少的因子,在信息损失最小的情况下对变量进行分类,不过有些朋友多spss因子 ...

  3. SOFARPC学习(一)

    接触SOFARPC,是从一个好朋友(女程序媛)的推荐开始,目的是从头到尾了解这个框架,包括使用方法和源码解析. 当学习一个新东西的事物,我总喜欢先总体把握,在深入细节,这样就可以有种高屋建瓴的感觉,否 ...

  4. 备忘录模式(Memento、Originator、Caretaker)(状态保存,备份恢复)

    定义:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.这样就可以将该对象恢复到原先保存的状态 类型:行为类 类图: 我们在编程的时候,经常需要保存对象的中间状态,当需要的时 ...

  5. 提升mysql服务器性能(复制原理与拓扑优化)

    原文:提升mysql服务器性能(复制原理与拓扑优化) 版权声明:皆为本人原创,复制必究 https://blog.csdn.net/m493096871/article/details/9008171 ...

  6. JAVA ——int 类型除法保留两位小数

    @Test public void txfloat() { // TODO 自动生成的方法存根 int a=9; int b=7; DecimalFormat df=new DecimalFormat ...

  7. 轮播图js版&jQ版

    JS版轮播图 html部分和css部分自己任意定 主要构成: 1,一个固定的框 超出框的部分隐藏 2,几张图片float:left 3,下部下原点,点击切换,切换到不同的张都有红色显示 4,左右两个大 ...

  8. Entrust - Laravel 用户权限系统解决方案 | Laravel China 社区 - 高品质的 Laravel 和 PHP 开发者社区 - Powered by PHPHub

    说明# Zizaco/Entrust 是 Laravel 下 用户权限系统 的解决方案, 配合 用户身份认证 扩展包 Zizaco/confide 使用, 可以快速搭建出一套具备高扩展性的用户系统. ...

  9. 大咖手把手教您,DLA一键建仓!

    DLA很早之前就支持了对关系型数据库的查询,但是一直以来用户会有一个担心: 直接分析RDS里面的数据会不会影响线上业务. 这个担心很合理,除非你要查询的RDS是专门用来做后台数据分析使用的,否则直接大 ...

  10. 模拟7题解 T1方程的解

    方程的解 [扩展欧几里德] 首先进行特判,两个小时基本想到了,除了a!=0,b==0,a*c<0这种情况 其次就是一般情况: 首先exgcd求出ax+by=GCD(a,b)的一组任意解 然后两边 ...