洛谷 P5072 Ynoi2015 盼君勿忘

2022-05-01 19:12:06 字數 1491 閱讀 3392

給定乙個序列,每次查詢乙個區間[l,r]中所有子串行分別去重後的和mod p

我們考慮每個數的貢獻。即該區間內含有這個數的子串行個數。用補集轉化為不含這個數的子串行個數。

那麼,假設這個數在[l,r]內出現了k次,則一共有2^(r-l+1) -2^(r-l+1-k)個子序列包含這個數。

本題可以離線,因此選擇使用莫隊,過程中維護cnt[k]表示區間內恰好出現k次的數字個數,維護sum[j]表示區間內恰好出現j次的數字之和(區間內出現次數相同的數,對於這些數,區間中包含這些數的子串行個數都相同,因此存數字之和就行)。

然而這樣時間複雜度為o(詢問次數*單次詢問複雜度)=o(n*max(sqrt(n),n))=o(nm),並不可行。我們發現時間瓶頸不在莫隊的sqrt(n),而是在單次查詢中求解的複雜度n。

有2個套路可供使用:出現次數大於sqrt(n)的數不超過sqrt(n)個,值不為0的cnt[k]少於2*sqrt(n)個(反證易得,本質類似)。

還沒完。我們發現模數是不定的,為了保證單次查詢的複雜度壓在sqrt(n)以內,我們還有最後一件事情要做:在sqrt(n)的時間內求出2^(r-l+1) 和所有的2^(r-l+1-k)。這裡安利乙個神奇的方式:每次查詢只需要做一次時間複雜度為sqrt(n)的預處理就可以o(1)查詢了。

假設查詢區間長度為len(len=r-l+1),我們記siz=sqrt(len),而後計算2^0 , 2^1 , 2^2 ... 2sqrt(len),存在陣列pow1中;再計算2sqrt(len) , 2^(2*sqrt(len)) , 2^(3*sqrt(len)) , 2^(4*sqrt(len))... , 2^(sqrt(len)*sqrt(len)),存在陣列pow[2]中。以上計算都在mod p意義下進行。

這樣求2的任意次方都可以o(1)出解:2^k =2^(k/siz) *2^(k%siz)=pow2[k/siz]*pow1[k%siz](記得模p)。

#include using namespace std;

#define maxn 100005

int n,m;

int a[maxn],val[maxn*2],cnt[maxn],ans[maxn];

int tot,blosiz,powsiz;

int bel[maxn],pow1[maxn],pow2[maxn];

bool calced[maxn];

long long sum[maxn];

struct query

} q[maxn];

void add(int x)

void del(int x)

int power(int x,int p)

int main()

ans[q[i].id]+=q[i].p;

ans[q[i].id]%=q[i].p;

} for (int i=1;i<=m;i++)

printf("%d\n",ans[i]);

return 0;

}

洛谷P3976 TJOI2015 旅遊

為了提高智商,zjy 準備去往乙個新世界去旅遊。這個世界的城市布局像一棵樹,每兩座城市之間只有一條路徑可以互達。每座城市都有一種寶石,有一定的 zjy 為了賺取最高利益,她會選擇從 a 城市 再轉手賣到 b 城市。由於zjy買寶石時經常賣萌,因而凡是 zjy 路過的城市,這座城市的寶石 會 讓我們來...

洛谷P2679 NOIP2015 子串

無 有兩個僅包含小寫英文本母的字串 a 和 b。現在要從字串 a 中取出 k 個互不重疊的非空子串,然後把這 k 個子串按照其在字串 a 中出現的順序依次連線起來得到一 個新的字串,請問有多少種方案可以使得這個新串與字串 b 相等?注意 子串取出 的位置不同也認為是不同的方案。輸入格式 輸入檔名為 ...

洛谷P3261 JLOI2015 城池攻占

不得不說,這道題目是真的難,真不愧它的 省選 noi 的紫色大火題!花了我晚自習前半節課看題解,寫 又花了我半節晚自習調 真的心態 基本上改得和題解完全一樣了我才過了這道題!真的煩。沒事,那接下來我來完全把這道題搞透。part 1 理解題目 至少我一開始不知道為什麼要用左偏樹,甚至我看題解一開始也都...