BZOJ 1014, 火星人

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010576722/article/details/54933375

Problem

传送门

Mean

给定一仅有小写字母组成的字符串,要求支持单字符修改、插入和查询不同起始位置的最长公共前缀长度。

Analysis

用Splay维护字符串,二分+Hash查询。
反反复复WA了很多次,就因为Hash的操作顺序不太对……也算是买了个教训。

Code

#include<cstdio>
#include<cstring>
typedef long long ll;
const int x=31,L=110005,MOD=1000173169;
int o,m,a,b,len,cnt,sz[L],f[L],v[L],son[L][2],p[L],h[L];
char c,s[L];
void up(int o){
    int l=son[o][0],r=son[o][1];
    sz[o]=sz[l]+sz[r]+1;
    h[o]=(h[l]+(ll)v[o]*p[sz[l]]%MOD+(ll)h[r]*p[sz[l]+1]%MOD)%MOD;
}
void read(int &x){
    char c;
    while((c=getchar())<'0' || c>'9');
    x=c-'0';
    while((c=getchar())>='0' && c<='9') x=x*10+c-'0';
}
void read(char &c){while(((c=getchar())<'A' || c>'Z') && (c<'a' || c>'z'));}
int build(int l,int r,int fa){
    int x=++cnt,mid=l+r>>1;
    f[x]=fa,v[x]=s[mid]-'a'+1;
    if(l<mid) son[x][0]=build(l,mid-1,x);
    if(r>mid) son[x][1]=build(mid+1,r,x);
    up(x);
    return x;
}
int kth(int k){
    for(int x=o,tmp;;){
        tmp=sz[son[x][0]]+1;
        if(tmp==k) return x;
        if(tmp>k) x=son[x][0];
        else x=son[x][1],k-=tmp;
    }
}
void rotate(int x){
    int y=f[x],w=son[y][1]==x;
    if(son[y][w]=son[x][w^1]) f[son[x][w^1]]=y;
    if(f[x]=f[y]) son[f[y]][son[f[y]][1]==y]=x;
    son[x][w^1]=y,f[y]=x;
    up(y);
}
void splay(int x,int w){
    while(f[x]!=w){
        int y=f[x];
        if(f[y]!=w){
            if((son[f[y]][0]==y)^(son[y][0]==x)) rotate(x);
            else rotate(y);
        }
        rotate(x);
    }
    if(!w) o=x;
    up(x);
}
int query(int x,int l){
    int a=kth(x),b=kth(x+l+1);
    splay(a,0),splay(b,a);
    return h[son[b][0]];
}
int solve(int x,int y){
    int l=1,r=cnt-y-1,ans=0;
    while(l<=r){
        int mid=l+r>>1;
        if(query(x,mid)==query(y,mid)) ans=mid,l=mid+1;
        else r=mid-1;   
    }
    return ans;
}
int main(){
    scanf("%s",s+1);
    len=strlen(s+1);
    p[0]=1;
    for(int i=1;i<L;i++) p[i]=(ll)p[i-1]*x%MOD;
    o=build(0,len+1,0);
    read(m);
    while(m--){
        read(c),read(a);
        if(c=='Q'){
            read(b);
            printf("%d\n",a<b?solve(a,b):solve(b,a));
        }else if(c=='R'){
            a=kth(a+1);
            splay(a,0);
            read(c);
            v[a]=c-'a'+1;
            up(a);
        }else{
            a=kth(a+1);
            splay(a,0);
            read(c);
            f[++cnt]=a,v[cnt]=c-'a'+1;
            son[cnt][1]=son[a][1],f[son[a][1]]=cnt,son[a][1]=cnt;
            up(cnt),up(a);
        }
    }
    return 0;
}

zju 1014

02-17

Operandrnrn--------------------------------------------------------------------------------rnrnTime limit: 30 Seconds Memory limit: 32768K rnTotal Submit: 325 Accepted Submit: 60 rnrn--------------------------------------------------------------------------------rnrnProfessor Maple teaches mathematics in a university. He have invented a function for the purpose of obtaining the operands from an expression. The function named op(i,e) can be described as follows: rnrnThe expression e may be divided into sub-expression(s) by the operator, which has the lowest priority in the expression. For example, the expression "a*b+b*c+c*d" should be divided into three sub-expressions "a*b", "b*c" and "c*d", because the operator "+" has the lowest priority. The purpose of this function is to extract the ith sub-expression as the result. So, in the example above, op(2,e)=b*c.rnrnrnIf we regard the sub-expression as the main expression, it might be divided again and again. Obviously, the dividing process is recursive. As you see, the following example is much more complex: rnrnLet p:=a^b*c+(d*c)^f*z+brnop(1,op(1,op(2,p)))=(d*c)rnop(1,op(1,op(1,op(2,p))))=d*crnop(2,op(2,p))=zrnop(3,p)=brnop(1,op(3,p))=brnrnProfessor Maple is so lazy that he would leave the work to computer rather than do it himself, when the expression is long and complicated. Of course, without your program, the computer won't work out the result automatically.rnrnrnInputrnrnThe input file contains several test cases. The last test case in the input file is followed by a line containing a symbol "*", indicating the end of the input data. Each test case consists of two parts. The first part describes the expression, while the second part contains several questions, which should be calculated according to the expression.rnrnThe first line of each test case contains an expression consists of the expression name, ":=" and the content of the expression. The expression name is a lowercase. And the content is composed by lowercases and operators "+", "(", ")", "*" and "^". For example, here is a valid expression, p:=a^b*c+(d*c)^f*z+b. Among those operators, "(" and ")" have the highest priority. The operator "^" has a lower priority, and then "*". The priority of the operator "+" is the lowest.rnrnThe second line of each test case contains an integer n indicating n questions based on the above expression. This is followed by n lines. Each of them contains the description of one question, which consists of integers. For example, the question with three integers "2 1 1" describes the function op(1,op(1,op(2,e))). To compute this function, we have to keep to the following sequence: First, according to the first integer 2, divide the expression and extract the 2nd sub-expression. Then, according to the second integer 1, divide the sub-expression and extract the 1st one. Finally, according to the third integer 1, divide the outcome again, and extract the result.rnrnrnOutputrnrnFor each test case, display the expression name and a colon on the first line. Then display the result of each question on a line. The layout of the output is shown in the sample output.rnrnYou may assume that all expressions and functions are always valid.rnDisplay a blank line between test cases.rnrnrnSample Inputrnrnp:=a^b*c+(d*c)^f*z+brn4rn2 1 1rn2 2rn3rn3 1rna:=(x+y)rn3rn1rn1 2rn1 2 1rn* rnrnrnOutput for the Sample InputrnrnExpression p:rnop(1,op(1,op(2,p)))=(d*c)rnop(2,op(2,p))=zrnop(3,p)=brnop(1,op(3,p))=brnrnExpression a:rnop(1,a)=x+yrnop(2,op(1,a))=yrnop(1,op(2,op(1,a)))=yrnrnrn我的程序:rn#include rn#include rn#include rn#include rn#include rn#include rnrnusing namespace std;rnrnifstream in("1014.in");rn//istream &in=cin;rnrnstring tostr(int a)rnrn string s;rn s.resize(1000);rn int count=0;rn if (a==0)rn return "0";rn while(a!=0)rn rn s[count++]=(char)(a%10+48);rn a/=10;rn rn s.resize(count);rn reverse(s.begin(),s.end());rn return s;rnrnrnmain()rnrn bool b=true;rn int qq;rn int i,ii,n,min,base,pos;rn char exp;rn char temp;rn string str,strbak;rn string tempstr;rn string pro,empty;rn int num,count;rn string result;rn in>>exp;rn while(exp!='*')rn rn if (b==false)rn cout<>temp;rn in>>temp;rn in>>str;rn in>>n;rn ws(in);rn strbak=str;rn for (ii=1;ii<=n;ii++)rn rn getline(in,tempstr);rn stringstream ss(tempstr);rn ws(ss);rn pro.resize(1);rn pro[0]=exp;rn while(ss.eof()==false)rn rn ss>>num;rn empty="op(";rn empty.append(tostr(num));rn empty.append(",");rn empty.append(pro);rn empty.append(")");rn pro=empty;rn result="";rn min=999999;pos=1000000;rn base=0;rn for (i=0;i1 || (num==1 && qq==1 && min%4!=0))rn rn result.resize(result.size()+1);rn result[result.size()-1]=str[i];rn rn rn /*rn while(result[0]=='(' && result[result.size()-1]==')')rn rn result.erase(&result[0]);rn result.erase(&result[result.size()-1]);rn rn */rn str=result;rn ws(ss);rn rn cout<>exp;rn rn return 0;rnrnrnrn太长了,有的地方写麻烦了可能大家也懒的看rn只希望有测试数据的朋友试试看到底什么地方不对。rn

没有更多推荐了,返回首页

私密
私密原因:
请选择设置私密原因
  • 广告
  • 抄袭
  • 版权
  • 政治
  • 色情
  • 无意义
  • 其他
其他原因:
120
出错啦
系统繁忙,请稍后再试