现在的位置: 首页 > 综合 > 正文

【splay】【bzoj 1895】: Pku3580 supermemo

2017年04月24日 ⁄ 综合 ⁄ 共 11120字 ⁄ 字号 评论关闭

http://www.lydsy.com/JudgeOnline/problem.php?id=1895

终于找到比较像样的模板题了

Orz 策爷单旋3s+ rank 3

我太弱双选无论怎么优化常数6s+

求神犇指导蒟蒻如何优化常数。。。。

难道写个struct会快。?

6540ms:

//#define _TEST _TEST
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
/************************************************
Code By willinglive    Blog:http://willinglive.cf
************************************************/
#define rep(i,l,r) for(int i=l,___t=(r);i<=___t;i++)
#define per(i,r,l) for(int i=r,___t=(l);i>=___t;i--)
#define MS(arr,x) memset(arr,x,sizeof(arr))
#define LL long long
#define INE(i,u,e) for(int i=head[u];~i;i=e[i].next)
inline const int read()
{
    int r=0,k=1;char c=getchar();
    for(;c<'0'||c>'9';c=getchar())if(c=='-')k=-1;
    for(;c>='0'&&c<='9';c=getchar())r=r*10+c-'0';
    return k*r;
}
/////////////////////////////////////////////////
const int N=200005;
int n,m;
int a[N],cnt;
int root,fa[N],c[N][2],sz[N],id[N];
int mi[N],w[N];
int add[N];bool rev[N];
int rec[N];
/////////////////////////////////////////////////
inline int min(int a,int b){return a<b?a:b;}
#define LS c[o][0]
#define RS c[o][1]
inline void pushup(int o)
{
    sz[o]=sz[LS]+sz[RS]+1;
    mi[o]=w[o];
    if(LS) mi[o]=min(mi[o],mi[LS]);
    if(RS) mi[o]=min(mi[o],mi[RS]);
}
inline void modify(int o,int x)
{
    if(!o)return;
    w[o]+=x;mi[o]+=x;add[o]+=x;
}
inline void flip(int o)
{
    if(!o)return;
    rev[o]^=1;
    swap(LS,RS);
}
inline void pushdown(int o)
{
    int tmp;
    if(tmp=add[o])
    {
        int l=LS,r=RS;
        modify(LS,tmp); modify(RS,tmp);
        add[o]=0;
    }
    if(rev[o])
    {
        flip(LS); flip(RS);
        rev[o]=0;
    }
}
void build(int l,int r,int o)
{
    int now=id[l],last=id[o];
    w[o]=mi[o]=a[o];
    if(l==r)
    {
        sz[now]=1;
        w[now]=mi[now]=a[l];
        add[now]=rev[now]=0;
        return;
    }
    RS=id[o+1+r>>1], fa[RS]=id[o];
    if(l^o) LS=id[l+o-1>>1], fa[LS]=id[o];
    if(l^o) build(l,o-1,l+o-1>>1); build(o+1,r,o+1+r>>1);
    pushup(o);
}
inline void reclaim(int o)
{
    if(!o) return;
    fa[o]=LS=RS=sz[o]=mi[o]=w[o]=add[o]=rev[o]=0;
    rec[++rec[0]]=o;
}
inline int newnode()
{
    if(rec[0]) return rec[rec[0]--];
    else return ++cnt;
}
int find(int o,int k)
{
	while(1)
	{
		pushdown(o);
		if(sz[LS]+1==k) return o;
		if(k<=sz[LS]) o=LS;
		else k-=sz[LS]+1,o=RS;
	}
}
inline void rot(int x,int &k)
{
    int y=fa[x],z=fa[y];
	bool f=*c[y]!=x;
    if(y==k)k=x;
    else c[z][*c[z]!=y]=x;
    int &t=c[x][!f];
    fa[x]=z; fa[y]=x; fa[t]=y;
    c[y][f]=t; t=y;
    pushup(y);
}
void splay(int x,int &k=root)
{
    while(x^k)
    {
        int y=fa[x],z=fa[y];
        if(y^k)
        {
            if(*c[y]==x^*c[z]==y) rot(x,k);
            else rot(y,k);
        }rot(x,k);
    }
}
void modify()
{
    int l=read(),r=read(),x=read(); r+=2;
    splay(l=find(root,l)); splay(r=find(root,r),c[root][1]);
    int o=c[r][0];
    add[o]+=x; w[o]+=x; mi[o]+=x;
}
void del()
{
    int x=read(),y=x,o;
    splay(x=find(root,x)); splay(y=find(root,y+2),c[root][1]);
    o=c[y][0]; reclaim(o); c[y][0]=0;
    pushup(y); pushup(x);
}
void insert()
{
    int pos=read()+1,x=read(),y=pos+1;
    splay(pos=find(root,pos)); splay(y=find(root,y),c[root][1]);
    int &o=c[y][0]=newnode();
    fa[o]=y;sz[o]=1;LS=RS=0;
    w[o]=mi[o]=x; add[o]=rev[o]=0;
    pushup(y); pushup(root);
}
void getmin()
{
    int l=read(),r=read(); r+=2;
    splay(l=find(root,l));
    splay(r=find(root,r),c[root][1]);
    printf("%d\n",mi[c[r][0]]);
}
void reverse()
{
    int l=read(),r=read(); r+=2;
    splay(l=find(root,l)); splay(r=find(root,r),c[root][1]);
    flip(c[r][0]);
}
void revolve()
{
    int l=read(),r=read(),k=read(); l++; r++;
    k%=(r-l+1);
    if(!k) return;
    int x=r-k,y=r+1;
    splay(x=find(root,x)); splay(y=find(root,y),c[root][1]);
    int tmp=c[y][0];
    c[y][0]=0;
    pushup(y); pushup(x);
    x=l-1; y=l;
    splay(x=find(root,x)); splay(y=find(root,y),c[root][1]);
    c[y][0]=tmp; fa[tmp]=y;
    pushup(y); pushup(x);
}
/////////////////////////////////////////////////
void input()
{
    n=read();
    rep(i,1,n) a[i+1]=read();
    n+=2; cnt=n;
    a[1]=a[n]=0x3fffffff;
    rep(i,1,n) id[i]=i;
}
void solve()
{
    char op[10];
    build(1,n,root=n+1>>1);
    m=read();
    while(m--)
    {
        scanf("%s",op);
        if(op[0]=='A') modify();
        else if(op[0]=='D') del();
        else if(op[0]=='I') insert();
        else if(op[0]=='M') getmin();
        else if(op[3]=='E') reverse();
        else revolve();
    }
}
/////////////////////////////////////////////////
int main()
{
    #ifndef _TEST
    freopen("std.in","r",stdin); freopen("std.out","w",stdout);
    #endif
    input(),solve();
    return 0;
}

改了一个小时的struct(今晚没事干么)貌似姿势还有点问题

删掉了回收功能,但代码复杂度增加了不少

3880ms

//#define _TEST _TEST
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
/************************************************
Code By willinglive    Blog:http://willinglive.cf
************************************************/
#define rep(i,l,r) for(int i=l,___t=(r);i<=___t;i++)
#define per(i,r,l) for(int i=r,___t=(l);i>=___t;i--)
#define MS(arr,x) memset(arr,x,sizeof(arr))
#define LL long long
#define INE(i,u,e) for(int i=head[u];~i;i=e[i].next)
inline const int read()
{
    int r=0,k=1;char c=getchar();
    for(;c<'0'||c>'9';c=getchar())if(c=='-')k=-1;
    for(;c>='0'&&c<='9';c=getchar())r=r*10+c-'0';
    return k*r;
}
/////////////////////////////////////////////////
const int N=200005;
int n,m;
int a[N],cnt;
int root,id[N];
int rec[N];
struct tree{
int o,fa,c[2],sz,mi,w,add;bool rev;
inline void pushup();
inline void modify(int x);
inline void flip();
inline void pushdown();
void build(int l,int r,int o);
}T[N];
/////////////////////////////////////////////////
inline int min(int a,int b){return a<b?a:b;}
#define LS c[0]
#define RS c[1]
inline void tree::pushup()
{
    sz=T[LS].sz+T[RS].sz+1;
    mi=w;
    if(LS) mi=min(mi,T[LS].mi);
    if(RS) mi=min(mi,T[RS].mi);
}
inline void tree::modify(int x)
{
    if(!this)return;
    w+=x;mi+=x;add+=x;
}
inline void tree::flip()
{
    if(!this)return;
    rev^=1;
    swap(LS,RS);
}
inline void tree::pushdown()
{
    int tmp;
    if(tmp=add)
    {
        int l=LS,r=RS;
        T[LS].modify(tmp); T[RS].modify(tmp);
        add=0;
    }
    if(rev)
    {
        T[LS].flip(); T[RS].flip();
        rev=0;
    }
}
void tree::build(int l,int r,int o)
{
    int now=id[l],last=id[o];
    w=mi=a[o];
    if(l==r)
    {
    	T[now].o=o;
        T[now].sz=1;
        T[now].w=T[now].mi=a[l];
        T[now].add=T[now].rev=0;
        return;
    }
    RS=id[o+1+r>>1], T[RS].fa=id[o];
    if(l^o) LS=id[l+o-1>>1], T[LS].fa=id[o];
    if(l^o) T[LS].build(l,o-1,l+o-1>>1); T[RS].build(o+1,r,o+1+r>>1);
    T[o].pushup();
}
int find(int o,int k)
{
	while(1)
	{
		T[o].pushdown();
		if(T[T[o].LS].sz+1==k) return o;
		if(k<=T[T[o].LS].sz) o=T[o].LS;
		else k-=T[T[o].LS].sz+1,o=T[o].RS;
	}
}
inline void rot(int x,int &k)
{
    int y=T[x].fa,z=T[y].fa;
	bool f=*T[y].c!=x;
    if(y==k)k=x;
    else T[z].c[*T[z].c!=y]=x;
    int &t=T[x].c[!f];
    T[x].fa=z; T[y].fa=x; T[t].fa=y;
    T[y].c[f]=t; t=y;
    T[y].pushup();
}
void splay(int x,int &k=root)
{
    while(x^k)
    {
        int y=T[x].fa,z=T[y].fa;
        if(y^k)
        {
            if(*T[y].c==x^*T[z].c==y) rot(x,k);
            else rot(y,k);
        }rot(x,k);
    }
}
void modify()
{
    int l=read(),r=read(),x=read(); r+=2;
    splay(l=find(root,l));
	splay(r=find(root,r),T[root].RS);
    int o=T[r].LS;
    T[o].modify(x);
}
void del()
{
    int x=read(),y=x,o;
    splay(x=find(root,x)); splay(y=find(root,y+2),T[root].RS);
    o=T[y].LS; T[y].LS=0;
    T[y].pushup(); T[x].pushup();
}
void insert()
{
    int pos=read()+1,x=read(),y=pos+1;
    splay(pos=find(root,pos)); splay(y=find(root,y),T[root].RS);
    int &o=T[y].LS=++cnt;
    T[o].o=o;
    T[o].fa=y; T[o].sz=1; T[o].LS=T[o].RS=0;
    T[o].w=T[o].mi=x; T[o].add=T[o].rev=0;
    T[y].pushup(); T[root].pushup();
}
void getmin()
{
    int l=read(),r=read(); r+=2;
    splay(l=find(root,l));
    splay(r=find(root,r),T[root].RS);
    printf("%d\n",T[T[r].LS].mi);
}
void reverse()
{
    int l=read(),r=read(); r+=2;
    splay(l=find(root,l)); splay(r=find(root,r),T[root].RS);
    T[T[r].LS].flip();
}
void revolve()
{
    int l=read(),r=read(),k=read(); l++; r++;
    k%=(r-l+1);
    if(!k) return;
    int x=r-k,y=r+1;
    splay(x=find(root,x)); splay(y=find(root,y),T[root].RS);
    int tmp=T[y].LS;
    T[y].LS=0;
    T[y].pushup(); T[x].pushup();
    x=l-1; y=l;
    splay(x=find(root,x)); splay(y=find(root,y),T[root].RS);
    T[y].LS=tmp; T[tmp].fa=y;
    T[y].pushup(); T[x].pushup();
}
/////////////////////////////////////////////////
void input()
{
    n=read();
    rep(i,1,n) a[i+1]=read();
    n+=2; cnt=n;
    a[1]=a[n]=0x3fffffff;
    rep(i,1,n) id[i]=i;
}
void solve()
{
    char op[10];
    root=n+1>>1;
    T[root].build(1,n,root=n+1>>1);
    m=read();
    while(m--)
    {
        scanf("%s",op);
        if(op[0]=='A') modify();
        else if(op[0]=='D') del();
        else if(op[0]=='I') insert();
        else if(op[0]=='M') getmin();
        else if(op[3]=='E') reverse();
        else revolve();
    }
}
/////////////////////////////////////////////////
int main()
{
    #ifndef _TEST
    freopen("std.in","r",stdin); freopen("std.out","w",stdout);
    #endif
    input(),solve();
    return 0;
}

Updated:Dec.5

成功借鉴了CLJ的模板超越了jcvb!!!

rank 3!!!!!

3456ms

这个好写多了,不过指针版太不熟悉,不容易调试

和Trie的模板趋于一致了

//#define _TEST _TEST
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
/************************************************
Code By willinglive    Blog:http://willinglive.cf
************************************************/
#define rep(i,l,r) for(int i=l,___t=(r);i<=___t;i++)
#define per(i,r,l) for(int i=r,___t=(l);i>=___t;i--)
#define MS(arr,x) memset(arr,x,sizeof(arr))
#define LL long long
#define INE(i,u,e) for(int i=head[u];~i;i=e[i].next)
inline const int read()
{int r=0,k=1;char c=getchar();for(;c<'0'||c>'9';c=getchar())if(c=='-')k=-1;
for(;c>='0'&&c<='9';c=getchar())r=r*10+c-'0';return k*r;}
/////////////////////////////////////////////////
const int N=200005;
const int inf=0x3fffffff;
#define LS c[0]
#define RS c[1]
int n,a[N],cnt;
struct node{
	node *c[2],*fa; int sz;
	int w,mi;
	int add; bool rev;
	bool d(){return this==fa->c[1];}
	void setc(node *ch,int x){c[x]=ch;ch->fa=this;}
	void Add(int x){w+=x; mi+=x; add+=x;}
	void Flip(){rev^=1;swap(LS,RS);}
	void pushup();
	void pushdown();
	void init();
	void build(int o,int l,int r);
}*root,*null,T[N];
int cntNode;
/////////////////////////////////////////////////
inline void pushrange(){root->RS->pushup();root->pushup();}
void node::pushup()
{
	sz=1;
	if(LS!=null) sz+=LS->sz;
	if(RS!=null) sz+=RS->sz;
	mi=w;
	if(LS!=null&&mi>LS->mi) mi=LS->mi;
	if(RS!=null&&mi>RS->mi) mi=RS->mi;
}
void node::pushdown()
{
	if(add)
	{
		if(LS!=null) LS->Add(add);
		if(RS!=null) RS->Add(add);
		add=0;
	}
	if(rev)
	{
		if(LS!=null) LS->Flip();
		if(RS!=null) RS->Flip();
		rev=0;
	}
}
node* NewNode()
{
	T[cntNode].init();
	return &T[cntNode++];
}
void node::build(int l,int r,int o)
{
	w=mi=a[o];
	if(l==r)
	{
		sz=1;
		w=mi=a[o];
		add=rev=0;
		return;
	}
	RS=NewNode(), RS->fa=this;
	if(l^o) LS=NewNode(), LS->fa=this;
	if(l^o) LS->build(l,o-1,l+o-1>>1); RS->build(o+1,r,o+1+r>>1);
	pushup();
}
void node::init()
{
	c[0]=c[1]=fa=null;
	sz=1;
	w=mi=0;
	add=rev=0;
}
void rot(node *o)
{
	node *f=o->fa; bool d=o->d();
	f->fa->setc(o,f->d());
	f->setc(o->c[!d],d);
	o->setc(f,!d);
	f->pushup();
}
void splay(node *o,node *k=null)
{
	while(o->fa!=k)
	{
		if(o->fa->fa==k) rot(o);
		else o->d()==o->fa->d()?(rot(o->fa),rot(o)):(rot(o),rot(o));
	}
	o->pushup();
	if(o->fa==null) root=o;
}
node* find(int k)
{
	int sz;
	for(node* o=root;;)
	{
		o->pushdown();
		sz=o->LS->sz;
		if(k==sz+1) return o;
		o=o->c[k>sz];
		if(k>sz) k-=sz+1;
	}
}
node* getrange(int l,int r)
{
	l--;r++;
	splay(find(l)); splay(find(r),root);
	return root->RS->LS;
}
void add()
{
	int l=read(),r=read(),x=read(); l++;r++;
	node *o=getrange(l,r);
	o->Add(x);
}
void del()
{
	int x=read(),y=x; x++; y++;
	node *o=getrange(x,x);
	root->RS->LS=o=null;
	pushrange();
}
void insert()
{
	int pos=read()+1,x=read(),y=pos+1;
	node *o=getrange(pos+1,pos);
	o=NewNode();
	o->Add(x);
	root->RS->setc(o,0);
	pushrange();
}
void getmin()
{
	int l=read(),r=read(); l++;r++;
	node* o=getrange(l,r);
	printf("%d\n",o->mi);
}
void reverse()
{
	int l=read(),r=read(); l++;r++;
	node *o=getrange(l,r);
	o->Flip();
}
void revolve()
{
	int l=read(),r=read(),k=read(); l++;r++;
	k%=(r-l+1);
	if(!k) return;
	node *tmp=getrange(r-k+1,r);
	root->RS->LS=null;
	pushrange();
	node *o=getrange(l,l-1);
	root->RS->setc(tmp,0);
	pushrange();
}
/////////////////////////////////////////////////
void input()
{
    n=read();
    rep(i,1,n) a[i+1]=read();
    n+=2; cnt=n;
    a[1]=a[n]=inf;
}
void solve()
{
    char op[10];
    null=NewNode(); null->sz=0;
    root=NewNode();
    root->build(1,n,n+1>>1);
    for(int m=read();m--;)
    {
    	scanf("%s",op);
    	if(op[0]=='A') add();
    	else if(op[0]=='D') del();
    	else if(op[0]=='I') insert();
    	else if(op[0]=='M') getmin();
    	else if(op[3]=='E') reverse();
    	else revolve();
    }
}
/////////////////////////////////////////////////
int main()
{
    #ifndef _TEST
    freopen("std.in","r",stdin); freopen("std.out","w",stdout);
    #endif
    input(),solve();
    return 0;
}

抱歉!评论已关闭.