bzoj3770 瘋狂的限制

2021-08-09 19:10:03 字數 1718 閱讀 4692

瘋狂的限制

題目背景:

bzoj3770

分析:算是暴力吧······

本來是在做

dp來著,然後看到這道題就一起做掉了······做了這道題終於發現,

vector

是多麼有用的東西······我們列舉右端點,那麼每次往右移動乙個,相當於加入了乙個字元,假設當前位置為

cur,

tot[i]

表示i ~ cur

所形成的子串滿足了多少條件,那麼新加進來的

s[cur + 1]

對tot

的影響其實非常小,他影響的就是所有字元為

s[cur + 1]

的限制的貢獻,(

c[i] == s[cur + 1]

),如果當前位置

cur + 1, 是第k

個s[cur + 1]

出現的位置,那麼影響到的貢獻位置就是第

k - l[i]

個s[cur + 1]

和第k - l[i] + 1

個s[cur + 1]

之間。還有第

k - r[i] - 1

和第k - r[i]

個s[cur + 1], 

那麼我們要做的就是快速找到每乙個限制字元為

s[cur + 1]

的限制,和上面所說的影響到的

s[cur + 1]

出現的位置,這兩者都可以很快的通過

vector

找到,然後暴力一發,注意邊界即可。

注意: 1

、關於邊界

我們可以預先在儲存每乙個字元出現位置的

vector

中預先放入

-1,這樣就可以很方便的更改開頭一段的貢獻了 2

、關於0

因為可能某些限制的

l[i] == 0

統計的時候可能會出現問題,所以需要單獨進行考慮。

source:

/*

created by scarlyw

*/#include #include #include #include #include #include #include #include #include #include const int maxn = 100000 + 10;

const int alp = 26;

const int maxm = 500 + 10;

char c;

char s[maxn];

int k, len, cnt, ans, l_limit, r_limit;

int q[maxm][3], tot[maxn];

long long final_ans;

std::vectorquery[alp];

std::vectorpos[alp];

inline void read_in()

}inline void solve()

if (size > q[p][2])

for (int j = pos[c][size - q[p][2] - 1] + 1;

j <= pos[c][size - q[p][2]]; ++j)

} final_ans += (long long)ans;

} printf("%lld", final_ans);

}int main()

3770 瘋狂的限制 亂搞

從左到右列舉子串的右區間,同時維護每個位置作為子串的左區間時能滿足的限制條件個數,將滿足條件個數在 l,r 的左區間統計入答案即可。設當前列舉的右區間為i,位置x作為左區間時滿足的限制條件個數為a x 現在將右區間改為i 1,如何維護a 首先a i 1 可以o k 判斷。對於某個限定條件c x l ...

BZOJ 2054 瘋狂的饅頭

time limit 10 sec memory limit 162 mb submit 449 solved 175 submit status 第一行四個正整數n,m,p,q 一共輸出n行,第i行表示第i個饅頭的最終顏色 如果最終顏色是白色就輸出0 4 3 2 422 30並查集。一看這道題認為...

bzoj 2054 瘋狂的饅頭

想到了要用一種東西維護下乙個沒被染色的是什麼東西,但是沒想到是並查集。這道題就相當於在每乙個集合裡的數都會跳到乙個相同的點,就相當於並查集的代表元素。如果將乙個點染色,就把它的父親設為i 1,這樣並查集的代表元素就是下乙個沒有被染色的點。include include include include...