飞机因为航空管制晚点了一个多小时,于是正好学习一下fhq介绍过的treap...
poj2352
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
int l[200000],r[200000],s[2000000],w[200000],x[200000],y[200000];
int ss,root,n,ans[200000];
bool random(double p)
{
return (double)rand()/RAND_MAX<p;
}
void print(int x)
{
if (!x) return ;
cout<<x<<' '<<l[x]<<' '<<r[x]<<endl;
print(l[x]),print(r[x]);
}
int ori(int x)
{
++ss,l[ss]=r[ss]=0;
w[ss]=x,s[ss]=1;
return ss;
}
void updata(int x)
{
s[x]=s[l[x]]+1+s[r[x]];
}
int merge(int x,int y)
{
if (!x) return y;
if (!y) return x;
if (random((double)s[x]/(s[x]+s[y]))) {
r[x]=merge(r[x],y),updata(x);
return x;
}
l[y]=merge(x,l[y]),updata(y);
return y;
}
void split(int root,int k,int &a,int &b)
{
if (!root) {
a=b=0;
return ;
}
if (w[root]>k) {
int p,q;
split(l[root],k,p,q);
l[root]=0,updata(root);
a=p,b=merge(q,root);
return ;
}
int p,q; //保证根节点被选
split(r[root],k,p,q);
r[root]=0,updata(root);
a=merge(root,p),b=q;
return ;
}
int ask(int x)
{
int a,b;
split(root,x,a,b);
int ans=s[a];
root=merge(a,b);
return ans;
}
int main()
{
freopen("input.txt","r",stdin);
scanf("%d",&n);
for (int i=1;i<=n;i++) scanf("%d%d",&x[i],&y[i]);
root=ss=0;
for (int i=1;i<=n;i++) {
int sum=ask(x[i]);
ans[sum]++;
int a,b;
split(root,x[i],a,b);
root=ori(x[i]);
root=merge(a,root),root=merge(root,b);
}
for (int i=0;i<n;i++) printf("%d\n",ans[i]);
return 0;
}
poj3580
上飞机前没调出来...
用叉姐的rand函数tle了,原因是值域只有32767,但是即便扩大范围也用了1900+ms,而黄哥的程序不但各种指针,stl,rand函数值域也只有32767还比我要快,难道真的是数组寻址太慢了不成...不过数据范围应该没那么大
值得一提的是我以前同样是数组实现的splay也比这个treap快的多,虽然说用这个treap处理某些操作非常方便...
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <ctime>
const int oo=1073741819;
const int Rand_Max=2147483647;
using namespace std;
int l[250000],r[250000],w[250000],s[250000],Min[250000];
int Ad[250000],Sw[250000];
int root,ss,n,m;
void print(int x)
{
if (!x) return ;
cout<<x<<' '<<l[x]<<' '<<r[x]<<endl;
print(l[x]);
print(r[x]);
}
inline int ran()
{
static int x = 1;
x += (x << 2) + 1;
return x & 2147483647;
}
bool random(double p)
{
return (double) (ran())/Rand_Max < p;
}
int ori(int x)
{
++ss,l[ss]=r[ss]=0;
w[ss]=x,s[ss]=1,Min[ss]=x;
Ad[ss]=0,Sw[ss]=0;
return ss;
}
void add(int x,int W)
{
if (!x) return ;
w[x]+=W,Ad[x]+=W,Min[x]+=W;
}
void swap(int x)
{
if (!x) return ;
int e;
e=l[x],l[x]=r[x],r[x]=e;
Sw[x]^=1;
}
void updata(int x)
{
if (!x) return ;
s[x]=s[l[x]]+s[r[x]]+1;
Min[x]=min(Min[l[x]],min(Min[r[x]],w[x]));
}
void pushdown(int x)
{
if (!x) return ;
if (Ad[x]) {
add(l[x],Ad[x]),add(r[x],Ad[x]);
Ad[x]=0;
}
if (Sw[x]) {
swap(l[x]),swap(r[x]);
Sw[x]=0;
}
updata(x);
}
int merge(int x,int y)
{
if (!x) return y;
if (!y) return x;
//if (random((double)s[x]/(s[x]+s[y]))) {
//if (w[x]<w[y]) {
if (ran()%(s[x]+s[y])<s[x]) {
pushdown(x);
r[x]=merge(r[x],y);
updata(x);
return x;
}
pushdown(y);
l[y]=merge(x,l[y]);
updata(y);
return y;
}
void split(int x,int k,int &a,int &b)
{
if (!x) {
a=b=0;
return ;
}
pushdown(x);
if (s[l[x]]>=k) {
int p,q;
split(l[x],k,p,q);
l[x]=0,updata(x);
a=p,b=merge(q,x);
return ;
}
int p,q;
split(r[x],k-(s[l[x]]+1),p,q);
r[x]=0,updata(x);
a=merge(x,p),b=q;
return ;
}
int main()
{
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
scanf("%d",&n);
root=ss=0,Min[0]=oo,s[0]=0,w[0]=oo;
for (int i=1;i<=n;i++) {
int x;
scanf("%d",&x);
int y=ori(x);
root=merge(root,y);
}
scanf("%d",&m);
char ch[200];
//print(root);
for (int i=1;i<=m;i++) {
scanf("%s",ch+1);
if ('A'==ch[1]) {
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
int a,b,c,d;
split(root,x-1,a,b);
split(b,y-x+1,c,d);
add(c,z);
root=merge(a,merge(c,d));
}
else if ('R'==ch[1] && 'E'==ch[4]) {
int x,y;
scanf("%d%d",&x,&y);
int a,b,c,d;
split(root,x-1,a,b);
split(b,y-x+1,c,d);
swap(c);
root=merge(a,merge(c,d));
}
else if ('R'==ch[1] && 'O'==ch[4]) {
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
//if ((z>(y-x+1))) continue;
z%=(y-x+1);
int a,b,c,d,e,f;
split(root,x-1,a,b);
split(b,y-x+1,c,d);
split(c,(y-x+1)-z,e,f);
root=merge(a,merge(f,merge(e,d)));
}
else if ('I'==ch[1]) {
int x,y;
scanf("%d%d",&x,&y);
int p=ori(y);
int a,b;
split(root,x,a,b);
root=merge(a,merge(p,b));
}
else if ('D'==ch[1]) {
int x;
scanf("%d",&x);
int a,b,c,d;
split(root,x-1,a,b);
split(b,1,c,d);
root=merge(a,d);
}
else if ('M'==ch[1]) {
int x,y;
scanf("%d%d",&x,&y);
int a,b,c,d;
split(root,x-1,a,b);
split(b,y-x+1,c,d);
int ans=Min[c];
root=merge(a,merge(c,d));
printf("%d\n",ans);
}
}
cout<<clock()<<endl;
return 0;
}
update 2014.4.14
去掉了一个无用的updata,时间减少了100ms,又去掉了split的两个merge,时间瞬间减少了400+ms
果然细节对常数的影响巨大,不过split的两个merge确实是没有必要的,但是叉姐的板子里面有...
update 2014.5.11
其实我也不知道去掉split的merge会不会导致树高不是log= =
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <ctime>
const int oo=1073741819;
const int Rand_Max=1073741819;
using namespace std;
int l[250000],r[250000],w[250000],s[250000],Min[250000];
int Ad[250000],Sw[250000];
int root,ss,n,m;
void print(int x)
{
if (!x) return ;
cout<<x<<' '<<l[x]<<' '<<r[x]<<endl;
print(l[x]);
print(r[x]);
}
inline int ran()
{
static int x = 1;
x += (x << 2) + 1;
return x & 1073741819;
}
bool random(double p)
{
return (double) (ran())/Rand_Max < p;
}
int ori(int x)
{
++ss,l[ss]=r[ss]=0;
w[ss]=x,s[ss]=1,Min[ss]=x;
Ad[ss]=0,Sw[ss]=0;
return ss;
}
void add(int x,int W)
{
if (!x) return ;
w[x]+=W,Ad[x]+=W,Min[x]+=W;
}
void swap(int x)
{
if (!x) return ;
int e;
e=l[x],l[x]=r[x],r[x]=e;
Sw[x]^=1;
}
void updata(int x)
{
if (!x) return ;
s[x]=s[l[x]]+s[r[x]]+1;
Min[x]=min(Min[l[x]],min(Min[r[x]],w[x]));
}
void pushdown(int x)
{
if (!x) return ;
if (Ad[x]) {
add(l[x],Ad[x]),add(r[x],Ad[x]);
Ad[x]=0;
}
if (Sw[x]) {
swap(l[x]),swap(r[x]);
Sw[x]=0;
}
//updata(x);
}
int merge(int x,int y)
{
if (!x) return y;
if (!y) return x;
//if (random((double)s[x]/(s[x]+s[y]))) {
//if (w[x]<w[y]) {
if (ran()%(s[x]+s[y])<s[x]) {
pushdown(x);
r[x]=merge(r[x],y);
updata(x);
return x;
}
pushdown(y);
l[y]=merge(x,l[y]);
updata(y);
return y;
}
void split(int x,int k,int &a,int &b)
{
if (!x) {
a=b=0;
return ;
}
pushdown(x);
if (s[l[x]]>=k) {
int p,q;
split(l[x],k,p,q);
l[x]=q,updata(x);
a=p,b=x;
return ;
}
int p,q;
split(r[x],k-(s[l[x]]+1),p,q);
r[x]=p,updata(x);
a=x,b=q;
return ;
}
int main()
{
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
scanf("%d",&n);
root=ss=0,Min[0]=oo,s[0]=0,w[0]=oo;
for (int i=1;i<=n;i++) {
int x;
scanf("%d",&x);
int y=ori(x);
root=merge(root,y);
}
scanf("%d",&m);
char ch[200];
//print(root);
for (int i=1;i<=m;i++) {
scanf("%s",ch+1);
if ('A'==ch[1]) {
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
int a,b,c,d;
split(root,x-1,a,b);
split(b,y-x+1,c,d);
add(c,z);
root=merge(a,merge(c,d));
}
else if ('R'==ch[1] && 'E'==ch[4]) {
int x,y;
scanf("%d%d",&x,&y);
int a,b,c,d;
split(root,x-1,a,b);
split(b,y-x+1,c,d);
swap(c);
root=merge(a,merge(c,d));
}
else if ('R'==ch[1] && 'O'==ch[4]) {
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
//if ((z>(y-x+1))) continue;
z%=(y-x+1);
int a,b,c,d,e,f;
split(root,x-1,a,b);
split(b,y-x+1,c,d);
split(c,(y-x+1)-z,e,f);
root=merge(a,merge(f,merge(e,d)));
}
else if ('I'==ch[1]) {
int x,y;
scanf("%d%d",&x,&y);
int p=ori(y);
int a,b;
split(root,x,a,b);
root=merge(a,merge(p,b));
}
else if ('D'==ch[1]) {
int x;
scanf("%d",&x);
int a,b,c,d;
split(root,x-1,a,b);
split(b,1,c,d);
root=merge(a,d);
}
else if ('M'==ch[1]) {
int x,y;
scanf("%d%d",&x,&y);
int a,b,c,d;
split(root,x-1,a,b);
split(b,y-x+1,c,d);
int ans=Min[c];
root=merge(a,merge(c,d));
printf("%d\n",ans);
}
}
//cout<<clock()<<endl;
return 0;
}