瘋狂的限制
題目背景:
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...