bzoj 1500 维修数列 bzoj 1507 editor

splay的裸题,一看就会,一写就错。这两道题真的把我弄恶心了。
一、update的时候没有考虑左右子树不存在的情况。
二、这道题卡内存,必须要用一个queue记录被删掉的节点编号,然后重复利用。
三、build的时候sz[mid]=1
四、删除节点不能直接tot-=k。因为不一定删除最后k个节点。
五、可以利用revit、makeit这种函数打标记。下放的时候直接revit(l),revit(r)。
六、1507不保证删除合法,要min一下,维护cnt又错了好多
1500
   
   
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#define ll int
#define inf (int) 1e9
#define mm (int) 1e9
#define N 1000010
using namespace std;
int fa[N],ch[N][2];
int mxl[N],mxr[N],mxans[N],mk[N],dt[N],sum[N],sz[N],a[N],id[N];
int root,tot;
bool rev[N];
queue<int> q;
bool dir(int x) { return ch[fa[x]][1]==x;}
void make(int x,ll d)
{
mk[x]=dt[x]=d; sum[x]=d*sz[x];
if (d>0)
{
mxans[x]=mxl[x]=mxr[x]=d*sz[x];
}
else
{
mxans[x]=mxl[x]=mxr[x]=d;
}
}
void revit(int x)
{
rev[x]^=1;
swap(mxl[x],mxr[x]);
}
void release(int x)
{
int l=ch[x][0],r=ch[x][1];
if (rev[x])
{
rev[x]=0;
swap(ch[x][0],ch[x][1]);
swap(l,r);
if (l) revit(l); if (r) revit(r);
}
if (mk[x]!=mm)
{
if (l) make(l,mk[x]); if (r) make(r,mk[x]);
mk[x]=mm;
}
}
void update(int x)
{
int l=ch[x][0],r=ch[x][1];
sz[x]=sz[l]+sz[r]+1;
mxans[x]=max(mxans[l],mxans[r]);
mxans[x]=max(mxans[x],max(dt[x],mxr[l]+dt[x]+mxl[r]));
mxans[x]=max(mxans[x],max(mxr[l]+dt[x],dt[x]+mxl[r]));
mxl[x]=max(max(mxl[l],sum[l]+dt[x]+mxl[r]),sum[l]+dt[x]);
mxr[x]=max(max(mxr[r],mxr[l]+dt[x]+sum[r]),dt[x]+sum[r]);
sum[x]=sum[l]+sum[r]+dt[x];
}

void rotate(int x)
{
int y=fa[x],z=fa[y],b=dir(x),c=dir(y),a=ch[x][!b];
if (z) ch[z][c]=x; else root=x;
if (a) fa[a]=y; fa[y]=x; fa[x]=z;
ch[x][!b]=y; ch[y][b]=a;
update(y); update(x);
}
void splay(int x,int i)
{
while (fa[x]!=i)
{
int y=fa[x],z=fa[y];
if (z==i) { release(y); release(x); rotate(x);}
else
{
release(z); release(y); release(x);
if (dir(y)==dir(x)) { rotate(y); rotate(x); }
else { rotate(x); rotate(x);}
}
}
}
int find_k(int x,int k)
{
release(x);
if (sz[ch[x][0]]==k) return x;
if (sz[ch[x][0]]>k) return find_k(ch[x][0],k);
return find_k(ch[x][1],k-sz[ch[x][0]]-1);
}
int find_min(int x)
{
release(x);
while (ch[x][0]) { x=ch[x][0]; release(x);}
return x;
}
int build(int l,int r,int al,int ar,int father)
{
if (l>r) return 0;
int mid=(l+r)>>1,x=id[mid],now=(al+ar)>>1;
fa[x]=father;
rev[x]=0; dt[x]=a[now]; mk[x]=mm; sz[x]=1;
ch[x][0]=build(l,mid-1,al,now-1,x);
ch[x][1]=build(mid+1,r,now+1,ar,x);
update(x);
return x;
}
void push(int x)
{
if (ch[x][0]) push(ch[x][0]);
q.push(x);
if (ch[x][1]) push(ch[x][1]);
}
void outit()
{
for (int i=1;i<=tot;i++) printf("%d %d %d %d %d %d\n",i,ch[i][0],ch[i][1],fa[i],sz[i],rev[i]);
printf("\n");
}
int main()
{
//freopen("1500.in","r",stdin); freopen("1500.out","w",stdout);
int n,tt,pos,sig; char st[15];
scanf("%d%d",&n,&tt); tot=n+2; mxl[0]=mxr[0]=mxans[0]=-inf;
for (int i=1;i<=n;i++) scanf("%d",&a[i+1]);
for (int i=1;i<=n+2;i++) id[i]=i;
root=build(1,n+2,1,n+2,0);
while (tt--)
{
scanf("%s",st);
switch (st[2])
{
case 'S': //insert
{
scanf("%d%d",&pos,&sig);
for (int i=1;i<=sig;i++) scanf("%d",&a[i]);
int x=find_k(root,pos); splay(x,0);
int y=find_min(ch[x][1]); splay(y,x);
for (int i=1;i<=sig;i++) if (!q.empty()) {id[i]=q.front(); q.pop(); } else id[i]=++tot;
ch[y][0]=build(1,sig,1,sig,y);
//tot+=sig;
update(y); update(x);
break;
}
case 'L': //delete
{
scanf("%d%d",&pos,&sig);
int x=find_k(root,pos-1); splay(x,0);
int y=find_k(ch[x][1],sig); splay(y,x);
push(ch[y][0]);
ch[y][0]=0; update(y); update(x);
//tot-=sig;
break;
}
case 'K'://make same
{
int d;
scanf("%d%d%d",&pos,&sig,&d);
int x=find_k(root,pos-1); splay(x,0);
int y=find_k(ch[x][1],sig); splay(y,x);
make(ch[y][0],d);
break;
}
case 'V'://reverse
{
scanf("%d%d",&pos,&sig);
int x=find_k(root,pos-1); splay(x,0);
int y=find_k(ch[x][1],sig); splay(y,x);
revit(ch[y][0]);
break;
}
case 'T'://get sum
{
scanf("%d%d",&pos,&sig);
int x=find_k(root,pos-1); splay(x,0);
int y=find_k(ch[x][1],sig); splay(y,x);
printf("%d\n",sum[ch[y][0]]);
break;
}
case 'X'://max sum
{
splay(1,0); splay(n+2,1);
printf("%d\n",mxans[ch[n+2][0]]);
break;
}
}
//outit();
}
return 0;
}

1507
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>

#define md
#define ll long long
#define inf (int) 1e9
#define eps 1e-8
#define N 5000010
using namespace std;
int fa[N],ch[N][2],sz[N];
char c[N];
char st[N];
int root,tot=0,now,cnt=0;
bool dir(int x) { return ch[fa[x]][1]==x;}
void update(int x)
{
sz[x]=sz[ch[x][0]]+1+sz[ch[x][1]];
}
void rotate(int x)
{
int y=fa[x],z=fa[y],b=dir(x),c=dir(y),a=ch[x][!b];
if (z) ch[z][c]=x; else root=x;
if (a) fa[a]=y; fa[y]=x; fa[x]=z;
ch[x][!b]=y; ch[y][b]=a;
update(y); update(x);
}
void splay(int x,int i)
{
while (fa[x]!=i)
{
int y=fa[x],z=fa[y];
if (z==i) rotate(x);
else
if (dir(y)==dir(x)) { rotate(y); rotate(x);}
else { rotate(x); rotate(x);}
}
}
int find_k(int x,int k)
{
//printf("find_k: %d %d\n",x,k);
if (sz[ch[x][0]]==k) return x;
if (sz[ch[x][0]]>k) return find_k(ch[x][0],k);
return find_k(ch[x][1],k-sz[ch[x][0]]-1);
}
int find_pre(int x)
{
x=ch[x][0];
while (ch[x][1]) x=ch[x][1];
return x;
}
int find_ne(int x)
{
x=ch[x][1];
while (ch[x][0]) x=ch[x][0];
return x;
}

void ycl()
{
tot=cnt=2;
root=1; fa[1]=0; ch[1][1]=2; sz[1]=2;
fa[2]=1; sz[2]=1;
}
void mid_dfs(int x)
{
if (ch[x][0]) mid_dfs(ch[x][0]);
putchar(c[x]);
if (ch[x][1]) mid_dfs(ch[x][1]);
}
int build(int l,int r,int bl,int br,int father)
{
if (l>r) return 0;
//printf("build: %d %d %d %d %d\n",l,r,bl,br,father);
int x=(l+r)>>1,nm=(bl+br)>>1;
fa[nm]=father; c[nm]=st[x]; sz[nm]=1;
ch[nm][0]=build(l,x-1,bl,nm-1,nm);
ch[nm][1]=build(x+1,r,nm+1,br,nm);
update(nm);
return nm;
}
void outit()
{
for (int i=1;i<=tot;i++) printf("%02d %02d %02d %02d %02d %c\n",i,ch[i][0],ch[i][1],fa[i],sz[i],c[i]);
}
int main()
{
freopen("1507.in","r",stdin); freopen("1507.out","w",stdout);
ycl();
int tt,k;
scanf("%d",&tt);
while (tt--)
{
scanf("%s",st);
switch (st[0])
{
case 'M': //move
{
scanf("%d",&k); now=k;
int x=find_k(root,k);
splay(x,0);
//printf(" solve mv: %c\n",c[x]);
break;
}
case 'I'://insert
{
scanf("%d",&k);
for (int i=1;i<=k;i++)
do { st[i]=getchar();} while (st[i]<32||st[i]>126);
int x=find_ne(root); splay(x,root);
ch[x][0]=build(1,k,tot+1,tot+k,x);
update(x); update(root);
tot+=k; cnt+=k;
//printf(" solve insert\n");
break;
}
case 'D'://delete
{
scanf("%d",&k); k=min(k,cnt-2-now);
int x=find_k(ch[root][1],k); splay(x,root);
ch[x][0]=0; update(x); update(root);
cnt-=k;
break;
}
case 'G'://get
{
scanf("%d",&k);
int x=find_k(ch[root][1],k); splay(x,root);
mid_dfs(ch[x][0]); printf("\n");
break;
}
case 'P'://prev
{
int x=find_pre(root); splay(x,0); now--;
break;
}
case 'N'://next
{
int x=find_ne(root); splay(x,0); now++;
break;
}
}
//outit();
}
return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值