【JSOI 2008】【BZOJ 1014】火星人prefix

这题其实很奇怪,一眼看出fhq treap+字符串hash。。。

结果在BZOJ被卡常了,结果学长告诉我了一些优化,有些自己还不会写,只写了inline和吧unsigned long long改为unsigned int。。。

结果时间少了一半,谁能告诉我为什么。。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
int m,len;
char s[100000];
unsigned int mi[200000];
struct treap_node{
    treap_node *left,*right;
    int fix,size;
    unsigned int hashz;
    char val;
    treap_node(char val): val(val) {left=right=NULL; fix=rand(); hashz=(int)(val)-96; size=1; }
    int lsize()
      {
        if (left)
          return left->size;
        else
          return 0;
      }
    int rsize()
      {
        if (right)
          return right->size;
        else
          return 0;
      }
    void Maintain()
      {
        size=1;
        size+=lsize()+rsize();
        hashz=(int)(val)-96;
        if (left&&!right)
          hashz=left->hashz+hashz*mi[lsize()];
        if (!left&&right)
          hashz=hashz+right->hashz*mi[1];
        if (left&&right)
          hashz=left->hashz+hashz*mi[lsize()]+right->hashz*mi[lsize()+1];
      }
};
treap_node *root;
typedef pair<treap_node*,treap_node*> droot;
inline treap_node *merge(treap_node *a,treap_node *b)
{
    if (!a) return b; if (!b) return a;
    if (a->fix<b->fix)
      {
        a->right=merge(a->right,b);
        a->Maintain();
        return a;
      }
    else
      {
        b->left=merge(a,b->left);
        b->Maintain();
        return b;
      }
}
inline droot split(treap_node *x,int k)
{
    if (!x) return droot(NULL,NULL);
    droot y;
    if (k<=x->lsize())
      {
        y=split(x->left,k);
        x->left=y.second;
        x->Maintain();
        y.second=x;
      }
    else
      {
        y=split(x->right,k-x->lsize()-1);
        x->right=y.first;
        x->Maintain();
        y.first=x;
      }
    return y;
}
inline void insert(int xi,char ch)
{
    droot x;
    treap_node *temp;
    x=split(root,xi);
    temp=new treap_node(ch);
    x.first=merge(x.first,temp);
    root=merge(x.first,x.second);
}
inline void del(int xi,int k)
{
    droot x,y;
    x=split(root,xi-1);
    y=split(x.second,1);
    root=merge(x.first,y.second);
}
inline void work(int x,int y)
{
    int l,r,mid,ans=0;
    unsigned int t1,t2;
    droot a,b;
    l=1; r=min(len-x+1,len-y+1);
    while (l<=r)
      {
        mid=(l+r)/2;
        a=split(root,x-1); b=split(a.second,mid);
        b.first->Maintain();
        t1=b.first->hashz;
        a.second=merge(b.first,b.second); root=merge(a.first,a.second);
        a=split(root,y-1); b=split(a.second,mid);
        b.first->Maintain();
        t2=b.first->hashz;
        a.second=merge(b.first,b.second); root=merge(a.first,a.second);
        if (t1==t2)
          l=mid+1,ans=mid;
        else
          r=mid-1;
      }
    printf("%d\n",ans);
}
int main()
{
    int i,x,y,t=0;
    char opt,ch;
    treap_node *temp;
    scanf("%s",&s);
    len=strlen(s);
    scanf("%d",&m);
    mi[0]=1;
    for (i=1;i<=100000;++i)
      mi[i]=mi[i-1]*27;
    for (i=0;i<=len-1;++i)
      {
        temp=new treap_node(s[i]);
        root=merge(root,temp);
      }
    for (i=1;i<=m;++i)
      {
        opt=getchar();
        while (opt!=‘Q‘&&opt!=‘R‘&&opt!=‘I‘)
          opt=getchar();
        if (opt==‘Q‘)
          {
            scanf("%d%d",&x,&y);
            work(x,y);
          }
        if (opt==‘I‘)
          {
            scanf("%d",&x);
            ch=getchar();
            while (ch<‘a‘||ch>‘z‘)
              ch=getchar();
            insert(x,ch);
            len++;
          }
        if (opt==‘R‘)
          {
            scanf("%d",&x);
            ch=getchar();
            while (ch<‘a‘||ch>‘z‘)
              ch=getchar();
            del(x,1);
            insert(x-1,ch);
          }
      }
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-10 02:15:17

【JSOI 2008】【BZOJ 1014】火星人prefix的相关文章

bzoj 1014 火星人prefix - 链表 - 分块

Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 8 9 10 11 字符 m a d a m i m a d a m 现在,火星人定义了一个函数LCQ(x, y),表示:该字符串中第x个字符开始的字串,与该字符串中第y个字符开始的字串,两个字串的公共前缀的长度.比方说,LCQ(1, 7) = 5, LCQ(2, 10) = 1, LCQ(4,

[BZOJ]1014 火星人prefix(JSOI2008)

一边听省队dalao讲课一边做题真TM刺激. BZOJ的discuss简直就是题面plus.大样例.SuperHINT.dalao题解的结合体. Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 8 9 10 11 字符 m a d a m i m a d a m 现在,火星人定义了一个函数LCQ(x, y),表示:该字符串中第x个字符开始的字串

BZOJ 1014 火星人prefix

Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 8 9 10 11 字符 m a d a m i m a d a m 现在,火星人定义了一个函数LCQ(x, y),表示:该字符串中第x个字符开始的字串,与该字符串中第y个字符开始的字串,两个字串的公共前缀的长度.比方说,LCQ(1, 7) = 5, LCQ(2, 10) = 1, LCQ(4,

BZOJ 1014 火星人 | 平衡树维护哈希

BZOJ 1014 火星人 题意 有一个字符串,三中操作:在某位置后面插入一个字符.修改某位置的字符.询问两个后缀的最长公共前缀. 题解 看到网上的dalao们都说这道题是平衡树,我就很懵x--平衡树维护什么啊? 最后发现某个节点维护的是它所代表的区间的哈希值--显然这个哈希值可以从左右子树的哈希值和这个节点上的字符算出来. #include <cstdio> #include <cmath> #include <cstring> #include <algori

【BZOJ】【1014】【JLOI2008】火星人prefix

Splay/二分/Hash 看了网上的题目关键字(都不用点进去看……我也是醉了)了解到做法= =那就上呗,前面做了好几道Splay的题就是为了练手搞这个的. Hash判断字符串是否相同应该很好理解吧?>_>我就不细说了 二分这个相同前缀的长度应该也容易>_> 用Splay维护这个Hash值>_>……也挺简单的,跟据size域就能算出以x为根的子树的hash值了. 这次我终于发现了一个之前以为不太重要的点……让我WA了两次= =!! 就是Splay在执行完序列插入的时候,

【二分+hash】【字符串】【平衡树】【JSOI 2008】火星人prefix

1014: [JSOI2008]火星人prefix Time Limit: 10 Sec Memory Limit: 162 MB Submit: 4264 Solved: 1306 Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 8 9 10 11 字符 m a d a m i m a d a m 现在,火星人定义了一个函数LCQ(x, y)

bzoj 1014: [JSOI2008]火星人prefix hash &amp;&amp; splay

1014: [JSOI2008]火星人prefix Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3154  Solved: 948[Submit][Status] Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 8 9 10 11 字符 m a d a m i m a d a m 现在,火星人

BZOJ 1014: [JSOI2008]火星人prefix( splay + hash )

用splay维护序列, 二分+hash来判断LCQ.. #include<bits/stdc++.h> using namespace std; typedef unsigned long long ull; const int maxn = 100009; const int P = 1000173169; ull K[maxn]; int N; char S[maxn]; struct Node { Node *ch[2], *p; int s, v; ull h; inline void

求帮看!!!!BZOJ 1014 [JSOI2008]火星人prefix

1014: [JSOI2008]火星人prefix Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 4164  Solved: 1277[Submit][Status][Discuss] Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 8 9 10 11 字符 m a d a m i m a d

【BZOJ 1014】 [JSOI2008]火星人prefix

1014: [JSOI2008]火星人prefix Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 3471  Solved: 1065 [Submit][Status] Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 8 9 10 11 字符 m a d a m i m a d a m 现在,