題意:第i天在原來字串的基礎上在字串的前面或者後面新增乙個字元。問新增完字元後有多少種不同長度的迴圈節。
定義迴圈節為能把原字串分割成長度為k的乙個或多個部分。並且後面可以有或者沒有迴圈節的開頭部分。
也就是說 s[1]~s[n-x] == s[x+1]~ s[n] 則說明迴圈節為x 。
1.明顯,對於長度為len的字串,最少有乙個長度為len的迴圈節。
2.答案單調性,如果乙個長度為r的字串有長度為x的迴圈節。那麼長度x~r的所有字串都有長度為x的迴圈節(手動模擬下可以證明,將原字串不斷刪去開頭或者末尾的字元必然還是滿足s[1]~s[n-x] == s[x+1]~ s[n])
同理如果長度為r的字串沒有長度為x的迴圈節,那麼長度大於r的字串也一定沒有長度為x的迴圈節(同樣手動模擬在字串後面或者前面新增字元)
那麼我們可以想到,對長度為i=(1~n)的迴圈節我們在原字串的第i~第n階段 進行二分。找到擁有迴圈節i 的最大字串長度r
那麼i~r 都有迴圈節i, 結果加1 那麼我們可以通過字首和的方式將區間修改 變成單點修改。讓a[i]++, a[r+1]-- 則字首和a[1]+...a[i]為
第i個階段的字串的迴圈節的種類數。
為了對字串二分。我們先把最終階段的字串hash,然後記錄一下每次變化後字串的左端點位置和右端點位置。
(具體做法是把head 設定為maxlen+1 ,tail 設定為maxlen+2 然後head往前減 tail往後加 最後把l[i]-=head, r[i]-=head則可以得到每個階段的左右端點)
然後每次二分check看l[i]~r[i]-x 是否等於x+1~r[i] 來判斷第i 階段可不可行。
總複雜度
#include#define ull unsigned long long
using namespace std;
const int maxn=2e6+6;
int n;
char s[10];
char ss[10];
int l[maxn],r[maxn],a[maxn];
struct hash
}ull query(int l,int r)
}hh;
bool check(int q,int x)
int main()
hh.get_hash(t+head+1);
for(int i=1;i<=n;i++)l[i]-=head,r[i]-=head;
for(int i=1;i<=n;i++)
a[r+1]--;
a[i]++;
}for(int i=1;i<=n;i++)
return 0;
}
題意:給你n個點,座標範圍為1e5 ,選不超過3條的橫線和不超過3條的豎線。相鄰線的距離固定為r,求位於這些線上的點的數量的最大值。
做法:用一棵線段樹維護值域上 第i, i+r, i+r*2 行上點的總數。 也就是說對於b[i] = a[i]+a[i+r]+a[i+r*2] 然後詢問整個區間的最大值。
(對於乙個x 他是 x,x-r , x-r*2 節點中的值, 所以這三個節點 需要變化)
#include#define ll long long
using namespace std;
const int maxn=100001;
int a[100005];
int b[100005];
int n,r;
vectorv[100005];
struct segment_tree
t[maxn*4];
void pushup(int o)
void build(int o,int l, int r)
int mid=(l+r)>>1;
build(o<<1,l,mid);
build(o<<1|1,mid+1,r);
pushup(o);
}void change(int o,int x,int d) // 單點更新
int mid=(t[o].l+t[o].r)>>1;
if(x<=mid)change(o<<1, x, d);
else change(o<<1|1, x, d);
pushup(o);
}int query(int o, int l, int r)
int mid=(t[o].l+t[o].r)>>1;
int mx=-1;
if(l<=mid)mx=max(query(o<<1,l,r),mx);
if(r>mid)mx=max(query(o<<1|1,l,r),mx);
return mx;
}int main()
for(int i=1;i<=maxn;i++)
build(1,1,maxn);
int ans=-1;
for(int i=1;i<=maxn;i++)
if(i+r<=maxn)
}if(i+r+r<=maxn)
}for(auto k:tmp)
ans=max(ans, (int)(tmp.size())+query(1,1,maxn) );
for(auto k:tmp)
}printf("%d\n",ans);
return 0;
}
2019牛客多校第十場
對於s n s n s n 考慮某個字母是從s n 1 s n 1 s n 1 轉移還是從s n 2 s n 2 s n 2 轉移 include define fo i,a,b for i a i b i define n 10005 using namespace std int t,n,q,p...
牛客第十場自閉
統計每個點連線邊的邊權和以及最大邊權,然後進行如下貪心 ll find ll x 將邊權存到了multisets x 這樣找到的ans是比答案大1倍的,因為每一條邊連向了兩個點,那麼每一條邊都被統計了2次答案,所以ans最後還要 2 也可以理解成以每個點為出發點,要往其他點連多少條邊 寫了詳細注釋 ...
2020牛客多校第十場 A
x 是乘法 以任意點為起點,一直以 2 x now p 第一類 做的話 或者3 x now p 第二類 會形成乙個或者多個環。環上有什麼特點。對於 某個數z,它所對應的後一位是y,當 2 x z p 3 x z p 相等的時候,這兩類的環在z後面的數y時一樣的。但是 上式化簡 2 x z n x p...