Jewel Magic UVA - 11996

来源:https://www.cnblogs.com/hehe54321/archive/2018/02/27/8480849.html
-Advertisement-
Play Games

Jewel Magic UVA - 11996 這是一道用splay/非旋treap做的題(這裡用的是非旋treap) 1/2/3是splay/非旋treap的常規操作。對於操作4,可以用哈希法求LCP。記hash(i,L)為子串[i,i+L-1](即第i個開始的L個)的hash值。記s[i]為序列 ...


Jewel Magic UVA - 11996

這是一道用splay/非旋treap做的題(這裡用的是非旋treap)

1/2/3是splay/非旋treap的常規操作。對於操作4,可以用哈希法求LCP。記hash(i,L)為子串[i,i+L-1](即第i個開始的L個)的hash值。記s[i]為序列第i位(編號從1開始),n為序列長度

如果通過某種方式做到能在O(logn)時間內取出一段子串的hash值,那麼二分答案(即LCP長度x),可以在O(logn)時間內判一個x是否合法(如果hash(l,x)==hash(r,x)則認為[l,l+x-1]和[r,r+x-1]是相同的,合法,否則不合法),可以做到在O(log^2n)內完成一個操作4。當然,hash判字元串是否相同正確性可能受影響,因此可以多計算一些hash,當他們都相同時才認為字元串相同,可以將錯誤率降到足夠小。

如何維護一段子串的hash值?首先定義x為任意整數,定義$hash(i,L)=s[i+L-1]*x^{L-1}+s[i+L-2]*x^{L-2}+...+s[i+1]*x+s[i]$

(這裡及之後都省略了取模)

(簡單記法:左邊乘的次數小)

(另一種記法:另一種求法的偽代碼表示:ans=0;for(j=i+L-1;j>=i;j--)  ans=ans*x+s[j];)

可以發現:如果已知hash(i,p)和hash(i+p,q)(即已知[i,i+p-1]和[i+p,i+p+q-1]的hash值),要求hash(i,p+q)(就是這兩段合起來的hash值),那麼:

令j=i+p,那麼$hash(i,p+q)$

$=s[j+q-1]*x^{p+q-1}+s[j+q-2]*x^{p+q-2}+...+s[j]*x^p+s[i+p-1]*x^{p-1}+...+s[i]*x^0$

所以$hash(i,p+q)=hash(j,q)*x^p+hash(i,p)=hash(i,p)+hash(i+p,q)*x^p$

這樣就得到了對於平衡樹某個節點,根據子節點為根的子樹的hash值與自身值求以自身為根的子樹的hash值的方法(先將左子樹和自身合起來,再將結果與右子樹合起來)

當然,由於此題有一個翻轉操作,對於一個節點要維護兩個hash:正向序列hash和反向序列hash。翻轉操作時順便交換一下兩個的值。

附:這道題沒有卡hash,單hash就能過,

附:聽說操作4有O(logn)的方法?待解決

錯誤記錄:

1.141行誤用build函數(build是用的左閉右閉區間),輸入了(a+1,a+n+1)。(然而不知道為什麼雖然過不了udebug的數據然而把題目A掉了)

2.沒註意在字元前還是字元後插入

*3.posib函數寫錯:沒有考慮要計算hash值的串超出長度範圍的情況(就是第二個"&&"之前的部分)。錯了不止一次

4.可能出現的錯誤:如果hash不用ull自然溢出,自己取模,那麼要考慮爆int、爆longlong、負數等等

  1 #include<cstdio>
  2 #include<algorithm>
  3 using namespace std;
  4 inline int rand1()
  5 {
  6     static int x=471;
  7     return x=(48271LL*x+1)%2147483647;
  8 }
  9 unsigned long long powx[400010];
 10 struct Node
 11 {
 12     Node(){}
 13     Node* ch[2];
 14     int r;
 15     bool flip;
 16     int v;
 17     unsigned long long h,rh;
 18     int size;
 19     void upd()
 20     {
 21         if(ch[0])   ch[0]->pd();
 22         if(ch[1])   ch[1]->pd();
 23         size=1+(ch[0]?ch[0]->size:0)+(ch[1]?ch[1]->size:0);
 24         h=(ch[0]?ch[0]->h:0)+v*powx[ch[0]?ch[0]->size:0]+(ch[1]?ch[1]->h:0)*powx[(ch[0]?ch[0]->size:0)+1];
 25         rh=(ch[1]?ch[1]->rh:0)+v*powx[ch[1]?ch[1]->size:0]+(ch[0]?ch[0]->rh:0)*powx[(ch[1]?ch[1]->size:0)+1];
 26     }
 27     void pd()
 28     {
 29         if(flip)
 30         {
 31             swap(ch[0],ch[1]);
 32             swap(h,rh);
 33             if(ch[0])   (ch[0]->flip)^=1;
 34             if(ch[1])   (ch[1]->flip)^=1;
 35             flip=0;
 36         }
 37     }
 38 }nodes[400010];
 39 Node* root;int mem;
 40 Node* getnode(){return nodes+(mem++);}
 41 Node* merge(Node* a,Node* b)
 42 {
 43     if(a==NULL)    return b;
 44     if(b==NULL)    return a;
 45     if(a->r < b->r)
 46     {
 47         a->pd();a->ch[1]=merge(a->ch[1],b);a->upd();
 48         return a;
 49     }
 50     else
 51     {
 52         b->pd();b->ch[0]=merge(a,b->ch[0]);b->upd();
 53         return b;
 54     }
 55 }
 56 typedef pair<Node*,Node*> P;
 57 P split(Node* a,int n)
 58 {
 59     if(a==NULL)    return P(NULL,NULL);
 60     P y;
 61     a->pd();int s=a->ch[0] ? a->ch[0]->size : 0;
 62     if(s>=n)
 63     {
 64         y=split(a->ch[0],n);
 65         a->ch[0]=y.second;a->upd();
 66         y.second=a;
 67     }
 68     else
 69     {
 70         y=split(a->ch[1],n-s-1);
 71         a->ch[1]=y.first;a->upd();
 72         y.first=a;
 73     }
 74     return y;
 75 }
 76 inline void insert(int k,int x)
 77 {
 78     Node* t=getnode();
 79     t->ch[0]=t->ch[1]=NULL;t->r=rand1();t->v=x;t->flip=0;t->upd();
 80     P y=split(root,k-1);
 81     root=merge(merge(y.first,t),y.second);
 82 }
 83 inline void erase(int k)
 84 {
 85     P y=split(root,k-1);
 86     P y2=split(y.second,1);
 87     root=merge(y.first,y2.second);
 88 }
 89 inline void reverse(int l,int r)
 90 {
 91     if(l>r) swap(l,r);
 92     P y=split(root,l-1);
 93     P y2=split(y.second,r-l+1);
 94     y2.first->flip^=1;
 95     root=merge(merge(y.first,y2.first),y2.second);
 96 }
 97 inline int size()
 98 {
 99     return root ? root->size : 0;
100 }
101 inline unsigned long long geth(int l,int r)
102 {
103     if(l>r)  return 0;
104     P y=split(root,l-1);
105     P y2=split(y.second,r-l+1);
106     unsigned long long ans=y2.first ? y2.first->h : 0;
107     root=merge(merge(y.first,y2.first),y2.second);
108     return ans;
109 }
110 Node* build(int *l,int *r)
111 {
112     if(l>r) return NULL;
113     if(l==r)
114     {
115         Node* t=getnode();
116         t->ch[0]=t->ch[1]=NULL;t->r=rand1();t->v=*l;t->flip=0;t->upd();
117         return t;
118     }
119     else
120     {
121         int* mid=l+(r-l)/2;
122         return merge(build(l,mid),build(mid+1,r));
123     }
124 }
125 int n,m,q;
126 int a[200010];
127 const int X=127;
128 int l,r;
129 inline bool posib(int x)
130 {
131     return (l+x-1<=size())&&(r+x-1<=size())&&(geth(l,l+x-1)==geth(r,r+x-1));
132 }
133 int main()
134 {
135     register int i;
136     int lx,rx,k,x,mid,tmp;
137     powx[0]=1;
138     for(i=1;i<=400000;i++)  powx[i]=powx[i-1]*X;
139     scanf("%d%d",&n,&q);
140     for(i=1;i<=n;i++)    scanf("%1d",&a[i]);
141     root=build(a+1,a+n);
142     while(q--)
143     {
144         scanf("%d",&tmp);
145         if(tmp==1)
146         {
147             scanf("%d%d",&k,&x);
148             insert(k+1,x);
149         }
150         else if(tmp==2)
151         {
152             scanf("%d",&k);
153             erase(k);
154         }
155         else if(tmp==3)
156         {
157             scanf("%d%d",&l,&r);
158             reverse(l,r);
159         }
160         else if(tmp==4)
161         {
162             scanf("%d%d",&l,&r);
163             lx=0;rx=size()+1;
164             while(rx-lx>1)
165             {
166                 mid=(lx+rx)>>1;
167                 if(posib(mid))  lx=mid;
168                 else    rx=mid;
169             }
170             printf("%d\n",lx);
171         }
172     }
173     return 0;
174 }

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 需求:搭建SSH框架環境,使用註解進行相關的註入(實體類的註解,AOP註解、DI註入),保存用戶信息 效果: 一、導依賴包 二、項目的目錄結構 三、web.xml配置 四、applicationContext.xml配置 五、log4j.properties配置 六、頁面代碼 index.jsp s ...
  • 【software construction】第一章 軟體構造的多維視角 - 描述軟體系統的三個維度 - 元素、關係和各種視角的模式 - 不同視角間的轉換 ...
  • 編寫一個類的方法,判斷某一年是否為閏年。閏年是西曆中的名詞,能被4整除但不能被100整除,或能被400整除的年份即為閏年。 import java.util.Scanner;public class isLeapYear { public static void main(String[] args ...
  • defaultdict函數將所有值初始化為指定類型 '' python按照引用傳遞 [1, 2, 3, 4] isinstance函數檢查對象是否為某個特定的類型 False is用來判斷兩份引用是否指向同一個對象與 == 不同 True 字元串左邊加上r表示字元應該按原本樣子解釋 e\\e str ...
  • 相信不少Springboot初學者和我一樣,都遇到上邊這個提示,明明路徑都是對的,但就是找不到對於的頁面而404了,這也困擾我很長一段時間,我也是不得其解,百度上也鮮有合理回答,因為以前使用的時候,明明一切都很正常,這也讓我疑神疑鬼了,一度懷疑是idea的問題,也重裝了,還建了很多次項目來實驗,這大 ...
  • Description 考慮正整數集合,現在有n組人依次來取數,假設第i組來了x人,他們每個取的數一定是x的倍數,並且是還剩下的最小的x個。正整數中有m個數被標成了幸運數,問有哪些人取到了幸運數。 考慮正整數集合,現在有n組人依次來取數,假設第i組來了x人,他們每個取的數一定是x的倍數,並且是還剩下 ...
  • 用戶模塊 要登陸後才能購買,因此我們先寫購買模塊. 設計實體 設計資料庫表 編寫DAO 測試DAO 抽取DAO 編寫Service 前臺樣式 head.jsp head.css 效果: 實現登陸註冊功能 當點擊登陸按鈕的時候,把數據帶過去給Servlet,讓Servlet調用BusinessServ ...
  • 介面的應用 介面是一種能力 關鍵字:interface 語法: 註:介面內,所有方法都沒有方法體 介面的特性: 介面不可以被實例化 常作為類型使用 實現類必須實現介面的所有方法 實現類可以實現多個介面 介面中的變數都是靜態常量 Java中的多繼承 生活中的介面: 電腦USB介面 引出: USB介面本 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...