zoukankan      html  css  js  c++  java
  • [NOI2003]文本编辑器

    题目:洛谷P4008、BZOJ1507。

    题目大意:
    一堆操作。
    1. 光标移动到指定位置
    2. 在光标后插入一串字符
    3. 在光标后删除一串字符
    4. 光标前移
    5. 光标后移
    6. 输出光标后的一串字符
    解题思路:
    非旋Treap即可,插入时一个一个字符插也没什么问题,开O2就可以过(BZOJ过不去)。

    C++ Code:

    #include<bits/stdc++.h>
    int t,rt=0,cnt=0,n,gb;
    struct node{
    	int r,ls,rs,sz;
    	char s;
    }a[5000005];
    char opt;
    inline void update(int x){a[x].sz=a[a[x].ls].sz+a[a[x].rs].sz+1;}
    int merge(int x,int y){
    	if(!x||!y)return x+y;
    	if(a[x].r<a[y].r){
    		a[x].rs=merge(a[x].rs,y);
    		update(x);
    		return x;
    	}else{
    		a[y].ls=merge(x,a[y].ls);
    		update(y);
    		return y;
    	}
    }
    void split(int u,int k,int& x,int& y){
    	if(k==0){x=0,y=u;return;}
    	if(a[u].sz==k){x=u,y=0;return;}
    	if(a[a[u].ls].sz>=k)split(a[u].ls,k,x,a[u].ls),y=u;else
    	split(a[u].rs,k-a[a[u].ls].sz-1,a[u].rs,y),x=u;
    	update(u);
    }
    void print(int now){
    	if(!now)return;
    	print(a[now].ls);
    	putchar(a[now].s);
    	print(a[now].rs);
    }
    inline int readint(){
    	int c=getchar(),d=0;
    	for(;!isdigit(c);c=getchar());
    	for(;isdigit(c);c=getchar())
    	d=(d<<3)+(d<<1)+(c^'0');
    	return d;
    }
    int main(){
    	srand(20170607);
    	memset(a,0,sizeof a);
    	gb=0;
    	for(t=readint();t--;){
    		opt=getchar();
    		for(;!isalpha(opt);opt=getchar());
    		if(opt=='I'){
    			n=readint();
    			int oldgb=gb;
    			while(n--){
    				char c=getchar();
    				while(c<32||c>126)c=getchar();
    				a[++cnt]=(node){rand(),0,0,1,c};
    				int x,y;
    				split(rt,gb++,x,y);
    				rt=merge(merge(x,cnt),y);
    			}
    			gb=oldgb;
    		}else
    		if(opt=='D'){
    			n=readint();
    			int x,y,z;
    			split(rt,gb,x,y);
    			split(y,n,y,z);
    			rt=merge(x,z);
    		}else
    		if(opt=='M')gb=readint();else
    		if(opt=='P')--gb,getchar(),getchar(),getchar();else
    		if(opt=='N')++gb,getchar(),getchar(),getchar();else{
    			n=readint();
    			int x,y,z;
    			split(rt,gb,x,y);
    			split(y,n,y,z);
    			print(y);putchar('
    ');
    			rt=merge(merge(x,y),z);
    		}
    		//print(rt);
    	}
    	return 0;
    }
    

    以下为笛卡尔树建树版本,跑的快了不止一点点,能在BZOJ上过了。

    C++ Code:

    #include<bits/stdc++.h>
    int t,rt=0,cnt=0,n,gb,top=0,sta[5000005];
    struct node{
    	int r,ls,rs,sz;
    	char s;
    }a[5000005];
    char opt,s[5000005];
    inline void update(int x){a[x].sz=a[a[x].ls].sz+a[a[x].rs].sz+1;}
    int merge(int x,int y){
    	if(!x||!y)return x+y;
    	if(a[x].r<a[y].r){
    		a[x].rs=merge(a[x].rs,y);
    		update(x);
    		return x;
    	}else{
    		a[y].ls=merge(x,a[y].ls);
    		update(y);
    		return y;
    	}
    }
    void split(int u,int k,int& x,int& y){
    	if(k==0){x=0,y=u;return;}
    	if(a[u].sz==k){x=u,y=0;return;}
    	if(a[a[u].ls].sz>=k)split(a[u].ls,k,x,a[u].ls),y=u;else
    	split(a[u].rs,k-a[a[u].ls].sz-1,a[u].rs,y),x=u;
    	update(u);
    }
    void print(int now){
    	if(!now)return;
    	print(a[now].ls);
    	putchar(a[now].s);
    	print(a[now].rs);
    }
    inline int readint(){
    	int c=getchar(),d=0;
    	for(;!isdigit(c);c=getchar());
    	for(;isdigit(c);c=getchar())
    	d=(d<<3)+(d<<1)+(c^'0');
    	return d;
    }
    int build(int n){
    	int x,pre;
    	for(int i=1;i<=n;++i){
    		a[x=++cnt]=(node){rand(),0,0,1,s[i]};
    		for(pre=0;top&&a[sta[top]].r>a[x].r;--top)update(pre=sta[top]);
    		if(top)a[sta[top]].rs=x;
    		a[sta[++top]=x].ls=pre;
    	}
    	while(top)update(sta[top--]);
    	return sta[1];
    }
    int main(){
    	srand(20170607);
    	memset(a,0,sizeof a);
    	gb=0;
    	for(t=readint();t--;){
    		opt=getchar();
    		for(;!isalpha(opt);opt=getchar());
    		if(opt=='I'){
    			n=readint();
    			for(int i=1;i<=n;++i){
    				char c=getchar();
    				while(c<32||c>126)c=getchar();
    				s[i]=c;
    			}
    			int x=build(n),y,z;
    			split(rt,gb,y,z);
    			rt=merge(merge(y,x),z);
    		}else
    		if(opt=='D'){
    			n=readint();
    			int x,y,z;
    			split(rt,gb,x,y);
    			split(y,n,y,z);
    			rt=merge(x,z);
    		}else
    		if(opt=='M')gb=readint();else
    		if(opt=='P')--gb,getchar(),getchar(),getchar();else
    		if(opt=='N')++gb,getchar(),getchar(),getchar();else{
    			n=readint();
    			int x,y,z;
    			split(rt,gb,x,y);
    			split(y,n,y,z);
    			print(y);putchar('
    ');
    			rt=merge(merge(x,y),z);
    		}
    		//print(rt);
    	}
    	return 0;
    }
    
  • 相关阅读:
    java基础知识回顾之java Thread类学习(三)--java线程实现常见的两种方式实现好处:
    java基础知识回顾之java Thread类--java线程实现常见的两种方式实现Runnable接口(二)
    java基础知识回顾之java Thread类--java线程实现常见的两种方式(一)
    java基础知识回顾之javaIO类--RandomAccessFile类
    java基础知识回顾之javaIO类--java序列化和反序列化
    X明X源面试题《三》
    X明X源面试题《二》
    SqlServer查询计划
    X明X源面试题《一》
    索引笔记《二》确定需要建立索引的列
  • 原文地址:https://www.cnblogs.com/Mrsrz/p/8820004.html
Copyright © 2011-2022 走看看