专栏文章
Atcoder ABC 395
个人记录参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @miq2krau
- 此快照首次捕获于
- 2025/12/03 21:55 3 个月前
- 此快照最后确认于
- 2025/12/03 21:55 3 个月前
思路:
维护三个值:
- 号鸟在的巢穴
- 号位置放的巢穴
- 号巢穴所在的位置
维护过程:
- 对于操作1:把鸟的位置移到位置,那么鸟的所在巢穴就变成了 , 即。
- 对于操作2:交换位置和位置的巢穴时,实际上就是, 因为就是个位置代表的巢穴。
- 对于操作3:当询问鸟所在的位置时,如果我们知道鸟所在的巢穴, 又知道号巢穴的位置,那么就可以得到鸟的真实位置。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int pos[N], id[N], g[N];
int main(){
int n;
cin >> n;
for(int i = 1; i <= n; i++) g[i] = i, pos[i] = i, id[i] = i;
int q;
cin >> q;
while(q--){
int op, a, b;
cin >> op;
if(op == 1){//改变鸟a所在的位置
cin >> a >> b;
pos[a] = g[b];//巢穴b的位置在g[b] 所以鸟a的位置就会变为g[b]
}else if(op == 2){
cin >> a >> b;//交换a位置和b位置的巢穴 那么g[a]和id[a]就会改变,b同理
id[g[a]] = b;
id[g[b]] = a;
swap(g[a], g[b]);//交换a号位置和b号位置的巢穴
}else {
cin >> a;
cout << id[pos[a]] << endl;
}
}
return 0;
}
思路:
建分层路,第一层图是原图,第二图图是反边
- 在同一层内的图的直接边权为1
- 如果要跨层的话,那么两层同个点的之间边权为
- 答案
- 最短路算法可选或者
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 5e5 + 10;
vector<pair<int, ll>>g[N];
ll dis[N];
int vis[N];
void dijkstra(){
priority_queue<pair<ll, int> >q;
memset(dis, 0x3f, sizeof dis);
q.push({1ll * 0, 1});
dis[1] = 0;
while(!q.empty()){
int u = q.top().second; q.pop();
if(vis[u]) continue;
vis[u] = 1;
for(auto cur: g[u]){
int v = cur.first;
ll w = cur.second;
if(dis[u] + w < dis[v]){
dis[v] = dis[u] + w;
q.push({-dis[v], v});
}
}
}
}
signed main() {
int n, m, x;
cin >> n >> m >> x;
for(int i = 1; i <= m; i++){
int u, v;
cin >> u >> v;
g[u].push_back({v, 1ll});
g[v + n].push_back({u + n, 1ll});
}
for(int i = 1; i <= n; i++){
g[i].push_back({i + n, 1ll * x});
g[i + n].push_back({i, 1ll * x});
}
dijkstra();
cout << min(dis[n], dis[2 * n]) << endl;
return 0;
}
思路:
条件1:
条件2:
二分, 然后
从条件看,对于每个上牙来说,必须满足:
- ,必须大于等于, 否则不满足条件。
- , 肯定小于等于, 否则, 也不满足条件
- 由此,得到的范围:
假设第个上牙,条件的限制范围为
从条件看,
- 第一个上牙可以认为不受限制,从第二个牙齿开始限制。那么第二个上牙的真实范围应该是和的交集
- 后面的上牙做法以此类推,每次用前个上牙得到的范围和第个上牙本身的范围取交集
- 如果最后交集为空,则无解,否则存在解
最后算出的高度为h,则答案为
CPP#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e6 + 5;
LL n,f,t,a[N],b[N],cut[N],mid,m,ans,L[N],R[N];
bool check(LL x){
for(int i = 1;i <= n;i ++)
L[i] = max(x - b[i],(LL)0),R[i] = a[i];
LL l = -1e12,r = 1e12;
for(int i = 1;i <= n;i ++){
l = max(l,L[i]);r = min(R[i],r);
if(l > r) return false;
l -= m;r += m;
}
return true;
}
int main(){
ios::sync_with_stdio(false);
cin>>n>>m;
LL l = 0,r = 1e12;
for(int i = 1;i <= n;i ++){
cin >> a[i] >> b[i];
r = min(r, a[i] + b[i]);
}
//r ++;//左闭右开区间
LL ans;
while(l <= r){
mid = l + r >> 1;
if(check(mid)) ans = mid, l = mid + 1;
else r = mid - 1;
}
LL res = 0;
for(int i = 1; i <= n;i ++)
res += (a[i] + b[i] - ans);
cout<<res;
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...