bzoj1058无限TLE(人傻自带常熟大的splay)

来源:互联网 发布:拍爱心的软件 编辑:程序博客网 时间:2024/04/25 14:06


T了5个点的splay

好吧,突然发现方法好像错了,不过学了一个splay_tree结构体的定义

#include<cstdio>#include<algorithm>#include<cstring>#include<cstdlib>#include<cmath>#include<iostream>#include<set>#define debug(x) cout<<#x<<"="<<x<<endlusing namespace std;const int N=1500010;const int inf=0x3f3f3f3f;struct splay_tree{int fa[N],ch[N][2],v[N],rt,tot;void rot(int x){int y=fa[x],z=fa[y],l,r;if (ch[y][0]==x) l=0;else l=1;r=l^1;if (z)if (ch[z][0]==y) ch[z][0]=x;else ch[z][1]=x;fa[x]=z;fa[y]=x;fa[ch[x][r]]=y;ch[y][l]=ch[x][r];ch[x][r]=y;}void splay(int x,int k){int y,z;while (fa[x]!=k){y=fa[x],z=fa[y];if (z!=k)if (ch[z][0]==y^ch[y][0]==x) rot(x);else rot(y);rot(x); }if (k==0) rt=x;}void insert(int val){if (rt==0) {rt=++tot;v[tot]=val;return ;}int y,i=rt;while (i){y=ch[i][v[i]<val];if (!y){v[++tot]=val;ch[i][v[i]<val]=tot;fa[tot]=i;i=tot;break;}i=y;}splay(i,0);}int find(int i,int val){if (i==0) return 0;if (v[i]==val) return i;if (v[i]>val) return find(ch[i][0],val);else return find(ch[i][1],val);}void del(int val){int k=find(rt,val);if (k==0) return ;splay(k,0);if (ch[k][0]==0&&ch[k][1]==0) {rt=0;return;}if (ch[k][0]==0){rt=ch[k][1];fa[rt]=0;return;}if (ch[k][1]==0){rt=ch[k][0];fa[rt]=0;return;}int y=ch[k][0];while (ch[y][1]) y=ch[y][1];splay(y,k);rt=y;fa[y]=0;ch[y][1]=ch[k][1];fa[ch[k][1]]=y; }int pre(int k){int y=ch[k][0];while (ch[y][1]) y=ch[y][1];return v[y];}int next(int k){int y=ch[k][1];while (ch[y][0]) y=ch[y][0];return v[y];}int min(){int y=rt;while (ch[y][0]) y=ch[y][0];splay(y,0);return v[y];}}s1,s2;int n,m,lx[N],rx[N],ans;int read(){int ans,f=1;char ch;while ((ch=getchar())<'0'||ch>'9') if (ch=='-') f=-1;ans=ch-'0';while ((ch=getchar())>='0'&&ch<='9') ans=ans*10+ch-'0';return ans*f;}void inin(int d){s2.insert(d);ans=min(ans,s2.next(s2.rt)-d);ans=min(ans,d-s2.pre(s2.rt));}void in(){int pos=read(),d=read();if (pos<n) s1.del(abs(rx[pos]-lx[pos+1]));s1.insert(abs(d-rx[pos]));if (pos<n) s1.insert(abs(d-lx[pos+1]));rx[pos]=d;inin(d);}int main(){n=read();m=read();for (int i=1;i<=n;i++) rx[i]=lx[i]=read();for (int i=1;i<n;i++) s1.insert(abs(lx[i+1]-lx[i]));s2.insert(inf);s2.insert(-inf);ans=inf;for (int i=1;i<=n;i++) inin(lx[i]);char c[20];while (m--){scanf("%s",c);if (c[0]=='I') in();if (c[4]=='G') printf("%d\n",s1.min());if (c[4]=='S') printf("%d\n",ans);}return 0;}


决定用set水过把,

吐槽一下:小Q竟然不会stl。。。。

不过stl能过,为什么同样思路的splay就过不了呢??呜呜呜~~,该不会是我写炸了吧

#include<cstdio>#include<set>#include<algorithm>#include<iostream>#define debug(x) cout<<#x<<"="<<x<<endlusing namespace std;const int inf=0x3f3f3f3f;multiset<int> num,diff;//一个存差值维护相邻差值,一个存总的数的集合multiset<int>::iterator it,last;int n,m,lx[500000],rx[500000],ans;int main(){scanf("%d%d",&n,&m);for (int i=1;i<=n;i++) {scanf("%d",&lx[i]);rx[i]=lx[i];num.insert(lx[i]);}for (int i=2;i<=n;i++) diff.insert(abs(lx[i]-lx[i-1]));ans=inf;num.insert(inf);num.insert(-inf);for (it=num.begin();it!=num.end();it++){if (it!=num.begin())ans=min(ans,*it-*last);//从左向右遍历,取集合最小差值last=it;}char ch[20];int pos,d;while (m--){scanf("%s",ch);if (ch[0]=='I'){scanf("%d%d",&pos,&d);it=diff.find(abs(rx[pos]-lx[pos+1]));diff.erase(it);//multiset,只能删除一个,就是应该删迭代器diff.insert(abs(rx[pos]-d));diff.insert(abs(d-lx[pos+1]));rx[pos]=d;it=num.insert(d);//set的insert函数是有返回值的返回所处的迭代器 ans=min(ans,d-*(--it));it++;it++;//这里要用--it,否则会错,++ -- 两个都是log的复杂度,就是前驱和后继ans=min(ans,*it-d);}elseif(ch[4]=='G') printf("%d\n",*diff.begin());//begin()最小值else printf("%d\n",ans);}return 0;}



0 0
原创粉丝点击