2021杭电多校第四场
1004: Display Substring
二分+后缀自动机
后缀自动机的每个节点有\(a[i].len-a[a[i].fa].len\)个字符串,且是连续的后缀如\(acbc、cbc、bc\),所以对于每个节点
它的权值根据字符串由长到短是递减的,所以我们可以二分答案,再对每个节点利用前缀和二分判断这个节点有多少大于答案的值,就能得到结果
#include <bits/stdc++.h>
const int maxn=1e5+50;
using namespace std;
#define int long long
int head[maxn<<1],nex[maxn<<1],to[maxn<<1],ecnt;
int size[maxn];
long long ans=0;
int dp[maxn];
struct node {
int ch[26];
int len,fa;
int pos;
} a[maxn<<1];
int pre=1,tot=1;
inline void init() {
pre=tot=1;
for(int i=0; i<26; i++) {
a[1].ch[i]=0;
}
ans=0;
a[1].len=0;
a[1].fa=0;
a[1].pos=0;
}
inline int newnode() {
++tot;
a[tot].len=0;
a[tot].fa=0;
a[tot].pos=0;
for(int i=0; i<26; i++) {
a[tot].ch[i]=0;
}
return tot;
}
inline void insert(int c,int i) {
int p=pre,np=pre=newnode();
size[tot]=1;
a[np].pos=i;
a[np].len=a[p].len+1;
for(; p&&!a[p].ch[c]; p=a[p].fa) a[p].ch[c]=np;
if(!p) a[np].fa=1;
else {
int q=a[p].ch[c];
if(a[q].len==a[p].len+1) a[np].fa=q;
else {
int nq=newnode();
a[nq]=a[q];
a[nq].len=a[p].len+1;
a[q].fa=a[np].fa=nq;
for(; p&&a[p].ch[c]==q; p=a[p].fa) a[p].ch[c]=nq;
}
}
}
int n,k;
int w[maxn];
char s[maxn];
int cnt;
int sum[maxn];
inline int ok(int val) {
int res=0;
for(int i=2; i<=tot; i++) {
int l=1,r=a[i].len-a[a[i].fa].len;
while(l<=r) {
int mid=l+r>>1;
if(sum[a[i].pos]-sum[a[i].pos-mid-a[a[i].fa].len]>val)r=mid-1;
else l=mid+1;
}
res=res+r;
}
if(res>=k)return 1;
else return 0;
}
const int inf=1e10+10;
signed main() {
int T;
scanf("%lld",&T);
int cas=0;
while(T--) {
cnt=0;
scanf("%lld %lld",&n,&k);
scanf("%s",s);
int len=strlen(s);
init();
for(int i=0; i<len; i++) insert(s[i]-'a',i+1);
for(int i=0; i<26; i++) {
scanf("%lld",&w[i]);
}
for(int i=1; i<=n; i++) {
sum[i]=sum[i-1]+w[s[i-1]-'a'];
}
int l=0,r=inf;
while(l<=r) {
int mid=l+r>>1;
if(ok(mid))r=mid-1;
else l=mid+1;
}
if(r!=inf) {
printf("%lld\n",l);
} else {
printf("-1\n");
}
cas++;
}
}
1008:Lawn of the Dead
转化为区间然后模拟一下
还有扫描线、并查集做法,不知道咋搞的
#include<bits/stdc++.h>
using namespace std;
#define int long long
typedef long long ll;
const int maxn = 1e5 + 10;
long long ans = 0;
int n, m, k;
bool vis[1010][1001];
int mp[1001][1001];
void dfs(int x, int y) {
if(x > n || y > m || vis[x][y] || mp[x][y]) return ;
vis[x][y] = 1;
ans ++;
dfs(x + 1, y);
dfs(x, y + 1);
}
int test() {
scanf("%lld %lld %lld", &n, &m, &k);
for(int i = 1; i <= n; ++ i) for(int j = 1; j <= m; ++ j) {
vis[i][j] = 0; mp[i][j] = 0;
}
for(int i = 0; i < k; ++ i) {
int x, y; scanf("%lld %lld", &x, &y);
mp[x][y] = 1;
}
ans = 0;
dfs(1, 1);
printf("%lld\n", ans);
return ans;
}
vector<int> v[maxn];
void run() {
int n, m, k, x, y; scanf("%d %d %d", &n, &m, &k);
for(int i = 1; i <= n; ++ i) v[i].clear();
for(int i = 0; i < k; ++ i) {
scanf("%d %d", &x, &y);
v[x].push_back(y);
}
for(int i = 1; i <= n; ++ i) sort(v[i].begin(), v[i].end());
vector<pair<int, int>> seg, tmp;
seg.push_back({1, 1});
long long ans = 0;
for(int i = 1; i <= n; ++ i) {
int now = 0, up = seg.size(), r;
if(!seg.size()) break;
r = seg[0].first;
for(auto it : v[i]) {
if(it < seg[now].first) r = it + 1;
else if(it == seg[now].first) {
seg[now].first ++;
if(seg[now].first > seg[now].second) now ++;
r = it + 1;
}
else {
tmp.push_back({seg[now].first, it - 1});
ans += it - seg[now].first;
if(it < seg[now].second) {
seg[now].first = it + 1;
r = it + 1;
}
else {
now ++;
r = it + 1;
while(now < up) {
if(seg[now].second < r) {
now ++; continue;
}
seg[now].first = max(r, seg[now].first);
break;
}
}
}
if(now == up) break;
}
if(now < up) {
tmp.push_back({max(seg[now].first, r), m});
ans += m - max(seg[now].first, r) + 1;
}
seg = tmp;
tmp.clear();
}
printf("%lld\n", ans);
}
signed main() {
//printf("%lld\n", test());
/*for(int i = 1; i <= n; ++ i) {
for(int j = 1; j <= m; ++ j) cout << vis[i][j] << " ";
cout << endl;
}*/
int t; scanf("%lld", &t);
while(t--) run();
return 0;
}

浙公网安备 33010602011771号