BZOJ2827 千山鸟飞绝 (离散+treap)

xiaoxiao2021-02-28  49

题目

题目链接

好长。。。。。 但是我觉得这个题目的名字特别好。

分析

尽管感觉是个很弱的题目,好歹是最为数据结构以及 treap的练手题目嘛 首先看起来我们就是需要数据结构去维护个什么东西 坐标比较散,所以我们可以先离散,排个序就可以了,但是要去重!?其实不去也是对的,因为每次都会选择同一个位置 然后就是修改操作 要支持查找最大值、统计元素个数、打上标记(而且是两个),还要分离合并 那么treap真是太好不过了。 时间复杂度O(t(logn+logt)) 呵呵,排序+查找的时间复杂度 还有就是最后的答案可能是LL

话说这里维护的对树的形态有关的那个权值我用的是鸟标号,但是正好也就是数组下标

然后

记得之前我说这个题目很弱,对不起我错啦。。。。 作为一个从来没有写个数据结构的家伙。。。。写了一上午才写出来呀。。。。 无限RE。。。。少主家题库是可以看数据的嘛。。。然后刷BZOJ真的好累啊。。。但是要练习,必须刷的。。 最后我是通过自己生成数据来找出了错误,也为查错找了一个方法嘛。。。 还有就是找到错误之后,不要改对了就算了,要看错误的根本原因,而不是掩耳盗铃地改个表面的东西额。

不过为什么其他人的代码这么短啊啊啊啊!!!

关于treap

真的是个很灵活的东西。 我感觉这次用的非常灵活啊。。 在按值分裂的时候,注意等于的情况是挂在哪个集合里面,看看代码就知道, v

代码

#include<cmath> #include<queue> #include<cstdio> #include<cctype> #include<vector> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define lc ch[now][0] #define rc ch[now][1] const int maxn=3e4+100,maxt=3e5+1000; struct XY{ int x,y; friend bool operator<(XY a,XY b) { return a.x!=b.x?a.x<b.x:a.y<b.y; } friend bool operator==(XY a,XY b) { return a.x==b.x&&a.y==b.y; } }p[maxn+maxt]; int cnt; struct data{ int w,x,y; void ins() { scanf("%d%d%d",&w,&x,&y); } }a[maxn],q[maxt]; struct Treap { int rt[maxt+maxn],ch[maxn][2],fix[maxn],w[maxn],sz[maxn],mx[maxn],mx_sz[maxn],mx_w[maxn],add_w[maxn],add_sz[maxn]; void Initial() { memset(w,0,sizeof(w)); memset(rt,0,sizeof(rt)); memset(ch,0,sizeof(ch)); memset(sz,0,sizeof(sz)); memset(mx,0,sizeof(mx)); memset(fix,0,sizeof(fix)); memset(mx_w,0,sizeof(mx_w)); memset(mx_sz,0,sizeof(mx_sz)); memset(add_w,0,sizeof(add_w)); memset(add_sz,0,sizeof(add_sz)); } int NewNode(int np,int v) { w[np]=mx[np]=v,sz[np]=1; fix[np]=rand(); return np; } void pushup(int now) { sz[now]=1; if(lc)sz[now]+=sz[lc]; if(rc)sz[now]+=sz[rc]; mx[now]=w[now]; if(lc)mx[now]=max(mx[now],mx[lc]); if(rc)mx[now]=max(mx[now],mx[rc]); } void pushdown(int now) { mx_sz[lc]=max(mx_sz[lc],add_sz[now]); mx_sz[rc]=max(mx_sz[rc],add_sz[now]); add_sz[lc]=max(add_sz[lc],add_sz[now]); add_sz[rc]=max(add_sz[rc],add_sz[now]); add_sz[now]=0; mx_w[lc]=max(mx_w[lc],add_w[now]); mx_w[rc]=max(mx_w[rc],add_w[now]); add_w[lc]=max(add_w[lc],add_w[now]); add_w[rc]=max(add_w[rc],add_w[now]); add_w[now]=0; } int Merge(int A,int B) { pushdown(A);pushdown(B); if(A*B==0)return A+B; if(fix[A]<fix[B]) { ch[A][1]=Merge(ch[A][1],B); pushup(A); return A; } else { ch[B][0]=Merge(A,ch[B][0]); pushup(B); return B; } } void Split(int now,int v,int &A,int &B) { pushdown(now); if(!now) { A=B=0; return; } if(v<now) { B=now; Split(lc,v,A,lc); } else { A=now; Split(rc,v,rc,B); } pushup(now); } int Find(int now,int v) { while(now) { pushdown(now); if(now==v)break; now=ch[now][v>now]; } return now; } void outs() { for(int i=1;i<=2;i++) { cout<<i<<" "<<sz[i]<<endl; } cout<<endl; } }tp; int n,m,sub[maxn]; void Init() { tp.Initial(); scanf("%d",&n); for(int i=1;i<=n;i++)a[i].ins(),p[i].x=a[i].x,p[i].y=a[i].y; scanf("%d",&m); for(int i=1;i<=m;i++)q[i].ins(),p[i+n].x=q[i].x,p[i+n].y=q[i].y; cnt=n+m; sort(p+1,p+cnt+1); cnt=unique(p+1,p+cnt+1)-p-1; } void add1(int i,int t) { int A,B,C; C=tp.NewNode(i,a[i].w); if(tp.rt[t]) { tp.mx_w[tp.rt[t]]=max(tp.mx_w[tp.rt[t]] , a[i].w); tp.add_w[tp.rt[t]]=max(tp.add_w[tp.rt[t]], a[i].w); tp.mx_sz[tp.rt[t]]=max(tp.mx_sz[tp.rt[t]] , tp.sz[tp.rt[t]]); tp.add_sz[tp.rt[t]]=max(tp.add_sz[tp.rt[t]], tp.sz[tp.rt[t]]); tp.mx_w[i]=max(tp.mx_w[i] , tp.mx[tp.rt[t]]); tp.mx_sz[i]=max(tp.mx_sz[i] , tp.sz[tp.rt[t]]); } tp.Split(tp.rt[t],i,A,B); tp.rt[t]=tp.Merge(tp.Merge(A,C),B); sub[i]=t; } void add2(int i,int t) { // if(sub[i]==t)return; int A,B,C; tp.Split(tp.rt[sub[i]],i-1,A,B); tp.Split(B,i,C,B); tp.rt[sub[i]]=tp.Merge(A,B); if(tp.rt[t]) { tp.mx_w[tp.rt[t]]=max(tp.mx_w[tp.rt[t]] , a[i].w); tp.add_w[tp.rt[t]]=max(tp.add_w[tp.rt[t]], a[i].w); tp.mx_sz[tp.rt[t]]=max(tp.mx_sz[tp.rt[t]] , tp.sz[tp.rt[t]]); tp.add_sz[tp.rt[t]]=max(tp.add_sz[tp.rt[t]], tp.sz[tp.rt[t]]); tp.mx_w[i]=max(tp.mx_w[i] , tp.mx[tp.rt[t]]); tp.mx_sz[i]=max(tp.mx_sz[i] , tp.sz[tp.rt[t]]); } tp.Split(tp.rt[t],i,A,B); tp.rt[t]=tp.Merge(tp.Merge(A,i),B); sub[i]=t; } void solve() { int t; for(int i=1;i<=n;i++) { t=lower_bound(p+1,p+cnt+1,(XY){a[i].x,a[i].y})-p; add1(i,t); } //tp.outs(); for(int i=1;i<=m;i++) { t=lower_bound(p+1,p+cnt+1,(XY){q[i].x,q[i].y})-p; add2(q[i].w,t); //tp.outs(); } } void outs() { for(int i=1;i<=n;i++) { tp.Find(tp.rt[sub[i]],i); cout<<1ll*tp.mx_w[i]*tp.mx_sz[i]<<'\n'; } } int main() { //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); Init(); solve(); outs(); return 0; }
转载请注明原文地址: https://www.6miu.com/read-2624330.html

最新回复(0)