[51nod1768]Rikka with Sequences
来源:互联网 发布:复旦大学香港大学知乎 编辑:程序博客网 时间:2024/06/14 09:09
题目描述
众所周知,萌萌哒六花不擅长数学,所以勇太给了她一些数学问题做练习,其中有一道是这样的:
勇太有一个长度为 n 的数组A 和一个大小为n×n 的二维数组B,最开始
接下来勇太进行了两种操作:
1. 给出两个整数 l 和 x ,把 A_l 的值变成x 。
2. 给出两个整数 l 和 r ,保证
在每次操作之后,勇太都会进行一次更新:
为了锻炼六花的计算能力,勇太希望六花能够尽可能快地回答他的问题。
当然,这个问题对于萌萌哒六花来说实在是太难了,你可以帮帮她吗?
输入数据保证 n,m≤105 , A_i,x≤109
分析
历史最小区间和无法用普通线段树实现,我们换个思路。
考虑维护B数组,把i看做x坐标,j看做y坐标,它就是二维空间的点集嘛,使用二维线段树维护?然而历史标记不能拆分,打起来也很麻烦。
考虑使用KD树,怎么用呢?使用KD树常用小技巧,离线先,把所有询问点抽出来建立KD树,然后考虑每个操作的影响。改变一个a_x,就相当于区间加减一堆点的值,这个区间的左下角是(1,x),右上角是(x,n);查询相当于查询一个点的历史最小值。
用吉如一论文经典维护历史标记做法即可。
KD树区间打标记的时候,KD树控制的区间和标记区间相离则退出,完全包含则打区间标记;否则递归下传,注意判断当前KD树实际代表点是否被覆盖,若覆盖则直接把改变加上去。
那么复杂度是
代码
#include<cstdio>#include<algorithm>#include<cmath>#include<cstring>#include<set>#include<map>using namespace std;#define cmax(a,b) (a=(a>b)?a:b)#define cmin(a,b) (a=(a<b)?a:b)#define fo(i,j,k) for(i=j;i<=k;i++)#define fd(i,j,k) for(i=j;i>=k;i--)typedef long long ll;typedef double db;const int N=4e5+5,mo=998244353,Q=1e6+5; struct rec{ int s,x,y,id,pid;}que[N];struct kd_tree{ int lx,ly,rx,ry; int x,y,ls,rs; ll v,mnv,tag,mntag;}tr[N];struct vec{ int x,y;}d[N];int ws,m,rt,lx,ly,rx,ry,a[N],n,i,td,x,v,ax,ay,tp;ll prt[N];multiset<vec> trs;bool cmp(vec a,vec b){ if (!ws) return a.x<b.x; return a.y<b.y;}bool operator <(vec a,vec b){ return a.x<b.x||a.x==b.x&&a.y<b.y;}int w[20],I;void Print(ll x){ w[0]=0; while (x) w[++w[0]]=x%10,x/=10; if (!w[0]) putchar('0'); fd(I,w[0],1) putchar(w[I]+'0'); putchar('\n');}void mt(int x,int y){ cmax(tr[x].rx,tr[y].rx); cmax(tr[x].ry,tr[y].ry); cmin(tr[x].lx,tr[y].lx); cmin(tr[x].ly,tr[y].ly);}int make(int l,int r,int s){ ws=s; int m=(l+r)/2; nth_element(d+l,d+m,d+r+1,cmp); s^=1; tr[m].lx=tr[m].rx=tr[m].x=d[m].x; tr[m].ly=tr[m].ry=tr[m].y=d[m].y; if (l<m) mt(m,tr[m].ls=make(l,m-1,s)); if (m<r) mt(m,tr[m].rs=make(m+1,r,s)); return m;}void down(int x){ int ls=tr[x].ls,rs=tr[x].rs; cmin(tr[ls].mntag,tr[x].mntag+tr[ls].tag); cmin(tr[rs].mntag,tr[x].mntag+tr[rs].tag); cmin(tr[x].mnv,tr[x].v+tr[x].mntag); tr[ls].tag+=tr[x].tag; tr[rs].tag+=tr[x].tag; tr[x].v+=tr[x].tag; tr[x].tag=tr[x].mntag=0;}void change(int x){ kd_tree &y=tr[x]; if (!x||y.rx<lx||y.lx>rx||y.ry<ly||y.ly>ry) return ; if (lx<=y.lx&&y.rx<=rx&&ly<=y.ly&&y.ry<=ry)// all in { y.tag+=v; cmin(y.mntag,y.tag); return ; } down(x); if (lx<=y.x&&y.x<=rx&&ly<=y.y&&y.y<=ry) // this in { y.v+=v; cmin(y.mnv,y.v); } change(y.ls); change(y.rs);}void thr(int x){ if (!x) return ; down(x); tr[x].mnv=tr[x].v; thr(tr[x].ls); thr(tr[x].rs);}ll get(int x){ if (!x||ax<tr[x].lx||ax>tr[x].rx||ay<tr[x].ly||ay>tr[x].ry) return 1e15; down(x); if (tr[x].x==ax&&tr[x].y==ay) return tr[x].mnv; return min(get(tr[x].ls),get(tr[x].rs));}void predo(){ rt=make(1,td,0); fo(i,1,n) { lx=1;rx=i;ly=i;ry=n;v=a[i]; change(rt); } thr(rt);}int main(){ freopen("t1.in","r",stdin); freopen("t1.out","w",stdout); scanf("%d %d",&n,&m); fo(i,1,n) scanf("%d",a+i); fo(i,1,m) { scanf("%d %d %d",&que[i].s,&que[i].x,&que[i].y); if (que[i].s==2) { d[++td].x=que[i].x; d[td].y=que[i].y; if (trs.find(d[td])!=trs.end()) td--; else trs.insert(d[td]); } } predo();// range from 1~n,1~n fo(i,1,m) { if (que[i].s==1) { x=que[i].x; lx=1;rx=x;ly=x;ry=n; v=que[i].y-a[x]; change(rt); a[x]=que[i].y; }else { ax=que[i].x;ay=que[i].y; prt[++tp]=get(rt); } } fo(i,1,tp) Print(prt[i]);}
阅读全文
0 0
- [51nod1768]Rikka with Sequences
- 51nod 1768 Rikka with Sequences KDtree维护历史最大值
- bestcoder Rikka with string
- Rikka with string
- hdu5204-Rikka with sequence
- Rikka with wood sticks
- HDU5202 Rikka with string
- hdu5202 Rikka with string
- Rikka with Graph
- hdu54235423 Rikka with Tree
- Bc Rikka with Graph
- A. Rikka with Chess
- Rikka with Chess
- Rikka with Graph<hdoj5631>
- Rikka with Parenthesis II
- hdu5828 Rikka with Sequence
- Rikka with Parenthesis II
- HDU5423 Rikka with Tree
- 初识负外边距在布局中的影响(1):基础理论
- Struts2框架学习---Three
- 有关 input默认宽度
- WebPack详细入门教程(六)之图片打包处理
- 封装类似jQuery的选择器
- [51nod1768]Rikka with Sequences
- VC获取默认浏览器
- 短信发送倒计时按钮封装,退出再进入可继续倒计时,绝对时间倒计时
- 实用的正则表达式整理
- SpringBoot 和 SpringMVC的异常统一处理
- PC硬件价格上涨原因找到了!原来是它
- 看图说话排序算法之希尔排序
- ES6 导出组件或属性 方式案例
- linux环境下,连接另一台服务器的oracle数据库,常见问题详解