您的位置:首页 > 其它

poj 3580 splay

2015-10-02 16:23 281 查看
这题没啥好说的。。。就是splay裸题。。然而我的splay的常数大得要死。弄了好久才过了。。。。

注意打标记的写法能有效减少常数。

然后还是数组流好了。。。妈蛋开结构体太蛋疼了。。。。不过结构体合并答案的时候是可以带来方便的,因此我们对于贮存答案的数组还是弄个结构体比较好,比如该死的最大连续子段和。。。。

代码:

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<string>
#define rep(i_,a,b) for(int i_=(a);i_<=(b);i_++)
using namespace std;
const int maxn=201200;
const int inf=2147483647;
int fa[maxn],c[maxn][2],siz[maxn],ans[maxn],mins[maxn],mark[maxn],key[maxn],sta[maxn];
bool rev[maxn];
int n,m,root,tot;
inline void release(int x){
if (x==0) return;
if (rev[x]){
swap(c[x][0],c[x][1]);
if (c[x][0]) rev[c[x][0]]=!rev[c[x][0]];
if (c[x][1]) rev[c[x][1]]=!rev[c[x][1]];
rev[x]=false;
}
if (mark[x]!=0){
if (c[x][0]) {
mark[c[x][0]]+=mark[x];
key[c[x][0]]+=mark[x];
mins[c[x][0]]+=mark[x];
}
if (c[x][1]) {
mark[c[x][1]]+=mark[x];
key[c[x][1]]+=mark[x];
mins[c[x][1]]+=mark[x];
}
mark[x]=0;
}
}
inline void updata(int x){
if (x==0) return;
release(x);
siz[x]=siz[c[x][0]]+siz[c[x][1]]+1;
mins[x]=key[x];
if (c[x][0]) mins[x]=min(mins[x],mins[c[x][0]]);
if (c[x][1]) mins[x]=min(mins[x],mins[c[x][1]]);
}
void link(int x,int y,int der){
if (x!=0) c[x][der]=y;
if (y!=0) fa[y]=x;
updata(x);
}
void cut(int x,int y,int der){
updata(x);
if (x!=0) c[x][der]=0;
if (y!=0) fa[y]=0;
updata(x);
}
inline void rorate(int x){
if (fa[x]==0) return ;
release(fa[x]);
release(x);
int t=fa[x],t1=fa[fa[x]];
int p=(c[t][1]==x);
int p1=(c[fa[t]][1]==t);

link(t1,x,p1);
link(t,c[x][!p],p);
link(x,t,!p);

updata(t);
}
inline void splay(int x,int y){
while (fa[x]!=y){

rorate(x);
}
updata(x);
if (y==0) root=x; else updata(y);
}
int getrank(int x,int k){

int i=x;
int j=k;
while (true){
release(i);
if (j==siz[c[i][0]]+1) return i;
if (siz[c[i][0]]+1<j) {
j-=(siz[c[i][0]]+1);
i=c[i][1];
} else{
i=c[i][0];
}
}
}
inline void getlr(int l,int r){
int lx=getrank(root,l);int rx=getrank(root,r);
splay(lx,0);
splay(rx,lx);
}
int  bt(int ff,int l,int r){
if (l>r) return 0;
if (l==r){
siz[l]=1;
fa[l]=ff;
updata(l);
return l;
}
int mid=(l+r)/2;
fa[mid]=ff;
c[mid][0]=bt(mid,l,mid-1);
c[mid][1]=bt(mid,mid+1,r);
updata(mid);
return mid;
}

string str;
char ss[10];
int main(){

scanf("%d",&n);
memset(rev,0,sizeof(rev));
rep(i,1,n){
scanf("%d",&key[i+1]);
}
key[1]=inf;
key[n+2]=inf;
tot=n+2;
root=bt(0,1,n+2);
scanf("%d",&m);
while (m--)
{
scanf("%s",ss);
str=string(ss);
if ( str == "ADD" ) {
int l , r , d; scanf( "%d%d%d" , &l , &r , &d );
getlr(l,r+2);
int t=c[c[root][1]][0];
mark[t]+=d;
key[t]+=d;
mins[t]+=d;
}
if ( str == "REVERSE" ) {
int l , r; scanf( "%d%d" , &l , &r );
getlr(l,r+2);
int t=c[c[root][1]][0];
rev[t]=!rev[t];
}
if ( str == "REVOLVE" ) {
int l , r , k; scanf( "%d%d%d" , &l , &r , &k );
int w=r-l+1;
k=((k%w)+w)%w;
if (k==0)continue;
getlr(r-k+1,r+2);
int t=c[c[root][1]][0];
cut(c[root][1],t,0);
getlr(l,l+1);
link(c[root][1],t,0);
}
if ( str == "INSERT" ) {
int x,p;scanf("%d%d",&x,&p);
getlr(x+1,x+2);
tot++;
key[tot]=p;
mins[tot]=p;
siz[tot]=1;
int t=c[root][1];
link(t,tot,0);
}
if ( str == "DELETE" ) {
int x,t;
scanf("%d",&x);
getlr(x,x+2);
t=c[root][1];
c[t][0]=0;
updata(t);
updata(root);
}
if ( str == "MIN" ) {
int l,r;scanf("%d%d",&l,&r);
getlr(l,r+2);
int t=c[c[root][1]][0];
updata(t);
printf("%d\n",mins[t]);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: