您的位置:首页 > 其它

HDU 4699 Editor

2013-08-22 18:19 302 查看
题意: 有一个光标,支持左移,右移,插入数字,删除数字,询问1~k最大前缀和。

解法: 用一个数据结构维护序列,答案可以DP出来。具体见代码。

手贱写了个Splay。其实链表就可以的吧。

本人第二弹Splay,支持旋转,插入,删除,查询第k位置。距离能当模板用貌似还有一段距离。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define clr(a,b) memset(a,b,sizeof(a));
#define REP(i,a,b) for(int i=(a); i<(b); i++)
const int INF = ~0u>>1;

// Splay
struct Node {
Node *ch[2];
int size;
int val;
int cmp(int x) const {
if(x == ch[0]->size + 1) return -1;
return x < ch[0]->size + 1 ? 0 : 1;
}
void pushup() {
size = ch[0]->size + ch[1]->size + 1;
}
};

Node *nill,*root;
int point;  // 光标位置

void init() {
nill = new Node();
nill->ch[0] = nill->ch[1] = nill;
nill->size = 0;
}

void rotate(Node* &o, int d) {
Node* tt = o;
o = o->ch[d^1];
tt->ch[d^1] = o->ch[d];
o->ch[d] = tt;
o->ch[d]->pushup();
o->pushup();
}

// 将左数第k个元素旋至根
void splay(Node* &o, int k) {
if(o == nill) return;
int d = o->cmp(k);
if(d == 1) k -= o->ch[0]->size + 1;
if(d != -1) {
Node* p = o->ch[d];
int d2 = p->cmp(k);
int k2 = (d2 == 0 ? k : k - p->ch[0]->size - 1);
if(d2 != -1) {
splay(p->ch[d2],k2);
if(d == d2) rotate(o,d^1); else rotate(o->ch[d],d);
}
rotate(o,d^1);
}
}

void INIT() {
root = new Node();
root->ch[0] = nill;
root->ch[1] = new Node();
root->ch[1]->ch[0] = root->ch[1]->ch[1] = nill;
root->size = 2;
root->ch[1]->size = 1;
}

void Insert(Node* &o, int pos, int x) {
splay(o,pos-1);
splay(o->ch[1],1);
o->ch[1]->ch[0] = new Node();
o->ch[1]->ch[0]->ch[0] = o->ch[1]->ch[0]->ch[1] = nill;
o->ch[1]->ch[0]->size = 1;
o->ch[1]->ch[0]->val = x;
o->ch[1]->pushup();
o->pushup();
}

void Delete(Node* &o, int pos) {
splay(o,pos);
splay(o->ch[0],pos-1);
Node* tt = o;
o=o->ch[0];
o->ch[1] = tt->ch[1];
delete tt;
o->pushup();
}

int query(Node* &o, int k) {
splay(o,k);
return o->val;
}

const int MAXN = 1001000;
int C[MAXN];
int mm[MAXN];

void Remove_Tree(Node* o) {
if(o == nill) return ;
Remove_Tree(o->ch[0]);
Remove_Tree(o->ch[1]);
delete o;
}

int main() {
int tot;
int nq;
init();
mm[0] = -INF;
while(~scanf("%d", &nq)) {
INIT();
point = 2;
char s[2];
int x;
tot = 2;
while(nq--) {
scanf("%s", s);
if(s[0] == 'I') {   // 在point插入一个数x,并且point后移
scanf("%d", &x);
Insert(root,point,x);
C[point-1] = C[point-2] + x;
mm[point-1] = max(mm[point-2], C[point-1]);
point ++ ;
tot ++ ;
}
else if(s[0] == 'D') {  // 把point位置前的数删除,并且point前移
if(point == 2) continue;
Delete(root,point-1);
point -- ;
tot -- ;
}
else if(s[0] == 'L') {  // point前移(在最前时不动)
if(point > 2) point -- ;
}
else if(s[0] == 'R') {  // point后移(在最后时不动)
if(point < tot) {
int tt = query(root,point);
C[point-1] = C[point-2] + tt;
mm[point-1] = max(mm[point-2], C[point-1]);
point ++;
}
}
else if(s[0] == 'Q') {  // 询问1~x范围内的最大前缀和
scanf("%d", &x);
printf("%d\n", mm[min(x,point-2)]);
}
}
Remove_Tree(root);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: