题解 | #i题 && e题#
区间
https://ac.nowcoder.com/acm/contest/87865/E
i题
思路:多次dj求解即可
#include <bits/stdc++.h>
using namespace std;
#define int long long
int inf = 1e13;
signed main(){
int n, m, k;
cin >> n >> m >> k;
vector<array<int,3>>g[n + 1];
for(int i = 1; i <= m; i++){
int a,b,c,d;
cin >> a>>b >> c>> d;
g[a].push_back({b,c,d});
g[b].push_back({a,c,d});
}
function<int(int,int,int)> get = [&](int s,int e,int f){
vector<int>vis(n + 1);
vector<int>dis(n + 1, inf);
dis[s] = 0;
priority_queue<pair<int,int>>q;
q.push({0, s});
while(q.size()){
auto [ds, id] = q.top();q.pop();
ds = -ds;
if(vis[id])continue;
vis[id] = 1;
for(auto [b,c,d]: g[id]){
if(f){ // 有钥匙
if(dis[b] > c + ds){
dis[b] = c + ds;
q.push({-dis[b], b});
}
}
else{
if(d == 0)continue;
else{
if(dis[b] > c + ds){
dis[b] = c + ds;
q.push({-dis[b], b});
}
}
}
}
}
return dis[e];
};
int dis1 = get(1, k, 0);
if(dis1 != inf){
int dis2 = get(k, n, 1);
int ans = get(1, n, 0);
cout << min(ans, dis1 + dis2) <<endl;
}
else{
int ans = get(1, n, 0);
cout << (ans == inf ? -1 : ans) << endl;
}
return 0;
}
e题
思路:暴力分块
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
const int M = 1010;
int a[N];
int be[N],L[M],R[M];
int tag[M];
int tagl[M],tagr[M];
void cg(int k){ // cg是维护的块的信息
int mx = 0, cnt = 0;
tagl[k] = -1;
tagr[k] = -1;
for(int i = L[k]; i <= R[k]; i++){
if(a[i])cnt ++;
else {
if(tagl[k] == -1)tagl[k] = cnt;
mx = max(mx, cnt);
cnt = 0;
}
}
if(tagl[k] == -1)tagl[k] = cnt;
tagr[k] = cnt;
mx = max(mx, cnt);
tag[k] = mx;
}
signed main(){
int n, q;
cin >> n >> q;
for(int i = 1; i <= n; i++) a[i] = 1;
int b = sqrt(n);
int ct = (n + b - 1) / b;
for(int i = 1; i <= ct; i++){
L[i] = (i - 1) * b + 1;
R[i] = min(n, i * b);
for(int j = L[i]; j <= R[i]; j++){
be[j] = i;
}
cg(i);
}
while(q--){
int op;
cin >> op;
if(op == 1){
int x; cin >> x;
a[x] ^= 1;
cg(be[x]);
}
else if(op == 2){
int l, r;cin >> l >> r;
if(be[l] == be[r]){
int mx = 0, cnt = 0;
for(int i = l; i <= r; i++){
if(a[i])cnt ++;
else {
mx = max(mx, cnt);
cnt = 0;
}
}
mx = max(mx, cnt);
cout << mx << endl;
}
else{
int mx = 0, cnt = 0;
for(int i = l; i <= R[be[l]]; i++){
if(a[i])cnt ++;
else {
mx = max(mx, cnt);
cnt = 0;
}
}
mx = max(mx, cnt);
int per = cnt;
int bkl = -1;
cnt = 0;
for(int i = L[be[r]]; i <= r; i++){
if (a[i])cnt++;
else{
if(bkl == -1)bkl = cnt;
mx = max(mx, cnt);
cnt = 0;
}
}
if(bkl == -1)bkl = cnt;
mx = max(mx, cnt);
// ct 个
cnt = per;
for(int k = be[l] + 1; k <= be[r] - 1; k++){
mx = max(mx, tag[k]);
if(tag[k] == R[k] - L[k] + 1){
cnt += R[k] - L[k] + 1;
}
else{
cnt += tagl[k];
mx = max(mx, cnt);
cnt = tagr[k];
}
}
mx = max(mx, cnt + bkl);
cout << mx << endl;
}
}
// for(int i = 1; i <= ct; i++){
// cout << "第"<< i <<"个块:" << tag[i] <<' ' << tagl[i] <<' ' << tagr[i] << endl;
// }
}
return 0;
}