参考博客
网上资料不少,留下自己AC代码方便以后回看,用的spt模板是博客里的
1、营业额统计
题目链接
题意:
求最小的营业额波动总和
最小的营业额波动=min(|x-y|),y是之前某天营业额
解法:
插入某个数,找前序以及后序即可
代码:
#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <stdlib.h>
#include <map>
#include <vector>
#define rep(i,n) for(i=0;i<n;i++)
#define cle(x) memset(x,0,sizeof(x))
#define ll long long
#define keyTree (ch[ ch[root][1] ][0])
const int maxn=100000+5;
using namespace std;
struct SplayTree{
int ch[maxn][2];
int pre[maxn];
int root,top1;
inline void Rotate(int x,int f)
{
//f=1 右旋 f=0 左旋
int y=pre[x];
ch[y][!f]=ch[x][f];
pre[ ch[x][f] ]=y;
pre[x]=pre[y];
if(pre[x])ch[ pre[y] ][ ch[pre[y]][1]==y]=x;
ch[x][f]=y;
pre[y]=x;
}
inline void Splay(int x,int goal) {
while(pre[x] != goal) {
if(pre[pre[x]] == goal) {
Rotate(x , ch[pre[x]][0] == x);
} else {
int y = pre[x] , z = pre[y];
int f = (ch[z][0] == y);
if(ch[y][f] == x) {
Rotate(x , !f) , Rotate(x , f);
} else {
Rotate(y , f) , Rotate(x , f);
}
}
}
if(goal == 0) root = x;
}
inline void NewNode(int &x,int c)
{
x=++top1;
ch[x][0]=ch[x][1]=pre[x]=0;
val[x]=c;
}
inline void Insert(int k)
{
int r=root;
if(r==0)
{
ch[0][0]=ch[0][1]=pre[0]=0;
NewNode(root,k);
return;
}
while(ch[r][val[r]<k])
{
r=ch[r][val[r]<k];
}
NewNode(ch[r][val[r]<k],k);
pre[ch[r][val[r]<k]]=r;
Splay(ch[r][val[r]<k],0);
}
inline int Getpre(int r)
{
while(ch[r][1])
r=ch[r][1];
return val[r];
}
inline int Getflo(int r)
{
while(ch[r][0])
r=ch[r][0];
return val[r];
}
inline void Work(int n)
{
root=top1=0;
ll ans=0;
for(int i=1;i<=n;i++)
{
int k;
if(scanf("%d",&k)==EOF)k=0;
Insert(k);
if(i==1)ans+=k;
else
{
int left=ch[root][0];
int right=ch[root][1];
int temp=0x3fffffff;
if(left){
temp=min(temp,k-Getpre(left));
}
if(right){
temp=min(temp,Getflo(right)-k);
}
ans+=(ll)temp;
}
}
printf("%I64d\n",ans);
}
int val[maxn];
}spt;
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
#endif
int n;
while(~scanf("%d",&n))
{
spt.Work(n);
}
return 0;
}
2、Double Queue (poj 3481)
题目链接
题意:
1:添加优先级为p的k号机器
2:去掉队列里优先级最高的机器
3:去掉队列里优先级最低的机器
解法:
2:min=while(ch[root][0]),splay(min,0),并删掉即可
3: 类似,伸展后无右子树
代码:
#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <stdlib.h>
#include <map>
#include <vector>
#define rep(i,n) for(i=0;i<n;i++)
#define cle(x) memset(x,0,sizeof(x))
#define ll long long
const int maxn=1000000+5;
using namespace std;
#define keyTree (ch[ ch[root][1] ][0])
struct SplayTree{
int ch[maxn][2];
int pre[maxn];
int root,top1;
inline void Rotate(int x,int f)
{
//f=1 右旋 f=0 左旋
int y=pre[x];
ch[y][!f]=ch[x][f];
pre[ ch[x][f] ]=y;
pre[x]=pre[y];
if(pre[x])ch[ pre[y] ][ ch[pre[y]][1]==y]=x;
ch[x][f]=y;
pre[y]=x;
}
inline void Splay(int x,int goal) {
while(pre[x] != goal) {
if(pre[pre[x]] == goal) {
Rotate(x , ch[pre[x]][0] == x);
} else {
int y = pre[x] , z = pre[y];
int f = (ch[z][0] == y);
if(ch[y][f] == x) {
Rotate(x , !f) , Rotate(x , f);
} else {
Rotate(y , f) , Rotate(x , f);
}
}
}
if(goal == 0) root = x;
}
inline void NewNode(int &x,int c,int p)
{
x=++top1;
ch[x][0]=ch[x][1]=pre[x]=0;
val[x]=c;
ip[x]=p;
}
inline void Insert(int k,int p)
{
int r=root;
if(r==0)
{
ch[0][0]=ch[0][1]=pre[0]=ip[0]=0;
NewNode(root,k,p);
return;
}
while(ch[r][val[r]<k])
{
r=ch[r][val[r]<k];
}
NewNode(ch[r][val[r]<k],k,p);
pre[ch[r][val[r]<k]]=r;
Splay(ch[r][val[r]<k],0);
}
inline int Getmin(int r)
{
while(ch[r][0])r=ch[r][0];
Splay(r,0);
return ip[r];
}
inline int Getmax(int r)
{
while(ch[r][1])r=ch[r][1];
Splay(r,0);
return ip[r];
}
inline void Work()
{
root=top1=0;
int op;
while(~scanf("%d",&op)){
int k,p;
if(op==1){
scanf("%d%d",&k,&p);
Insert(p,k);
}
else if(op==3)
{
int temp=ip[root];
int left=ch[root][0];
if(left)
temp=Getmin(left);
int right=ch[root][1];
pre[right]=0;
root=right;
printf("%d\n",temp);
}
else if(op==2)
{
int temp=ip[root];
int right=ch[root][1];
if(right)
temp=Getmax(right);
int left=ch[root][0];
pre[left]=0;
root=left;
printf("%d\n",temp);
}
else{
break;
}
// debug();
}
}
int val[maxn];
int ip[maxn];
}spt;
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
#endif
spt.Work();
return 0;
}
最后献上 poj 3468段更新 by notonlysuccess
#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <stdlib.h>
#include <map>
#include <vector>
#define rep(i,n) for(i=0;i<n;i++)
#define cle(x) memset(x,0,sizeof(x))
#define ll long long
#define keyTree (ch[ ch[root][1] ][0])
const int maxn=200000+5;
using namespace std;
struct SplayTree{
int sz[maxn];
int ch[maxn][2];
int pre[maxn];
int root,top1,top2;
int ss[maxn],que[maxn];
inline void Rotate(int x,int f)
{
//f=1 右旋 f=0 左旋
int y=pre[x];
push_down(y);
push_down(x);
ch[y][!f]=ch[x][f];
pre[ ch[x][f] ]=y;
pre[x]=pre[y];
if(pre[x])ch[ pre[y] ][ ch[pre[y]][1]==y]=x;
ch[x][f]=y;
pre[y]=x;
push_up(y);
}
inline void Splay(int x,int goal) {
push_down(x);
while(pre[x] != goal) {
if(pre[pre[x]] == goal) {
Rotate(x , ch[pre[x]][0] == x);
} else {
int y = pre[x] , z = pre[y];
int f = (ch[z][0] == y);
if(ch[y][f] == x) {
Rotate(x , !f) , Rotate(x , f);
} else {
Rotate(y , f) , Rotate(x , f);
}
}
}
push_up(x);
if(goal == 0) root = x;
}
inline void RotateTo(int k,int goal) {//把第k位的数转到goal下边
int x = root;
push_down(x);
while(sz[ ch[x][0] ] != k) {
if(k < sz[ ch[x][0] ]) {
x = ch[x][0];
} else {
k -= (sz[ ch[x][0] ] + 1);
x = ch[x][1];
}
push_down(x);
}
Splay(x,goal);
}
inline void NewNode(int &x,int c)
{
x=++top1;
ch[x][0]=ch[x][1]=pre[x]=0;
sz[x]=1;
val[x]=sum[x]=c;
add[x]=0;
}
inline void push_down(int x)
{
if(add[x])
{
val[x]+=add[x];
int left=ch[x][0];
int right=ch[x][1];
add[left]+=add[x],add[right]+=add[x];
sum[left]+=(ll)sz[left]*add[x];
sum[right]+=(ll)sz[right]*add[x];
add[x]=0;
}
}
inline void push_up(int x)
{
int left=ch[x][0];
int right=ch[x][1];
sz[x]=1+sz[left]+sz[right];
sum[x]=add[x]+val[x]+sum[left]+sum[right];
}
inline void makeTree(int &x,int l,int r,int f)
{
if(l>r)
return;
int mid=(l+r)>>1;
NewNode(x,num[mid]);
makeTree(ch[x][0],l,mid-1,x);//左子树
makeTree(ch[x][1],mid+1,r,x);
pre[x]=f;
push_up(x);
}
inline void init(int n)
{
ch[0][0]=ch[0][1]=pre[0]=sz[0]=0;
add[0]=sum[0]=0;
root=top1=0;
NewNode(root,-1);
NewNode(ch[root][1],-1);
pre[top1]=root;
sz[root]=2;
for(int i=0;i<n;i++)
scanf("%d",&num[i]);
makeTree(keyTree,0,n-1,ch[root][1]);
push_up(ch[root][1]);
push_up(root);
}
inline void update()
{
int l,r,c;
scanf("%d%d%d",&l,&r,&c);
RotateTo(l-1,0);
RotateTo(r+1,root);
add[keyTree]+=c;
sum[keyTree]+=(ll)c*sz[keyTree];
}
inline void query()
{
int l,r;
scanf("%d%d",&l,&r);
RotateTo(l-1,0);
RotateTo(r+1,root);
printf("%I64d\n",sum[keyTree]);
}
int num[maxn];
int val[maxn];
int add[maxn];
ll sum[maxn];
}spt;
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
#endif
int n,m;
scanf("%d%d",&n,&m);
spt.init(n);
while(m--)
{
char op[10];
scanf("%s",&op);
if(op[0]=='Q')
spt.query();
else
spt.update();
}
return 0;
}