0%

思路讲解

行上面反转,使列上面为排列。

注意到,可以对称的操作,反转1,i,使得 i 为首,再反转N-i+1,N,

1
2
3
4
5
6
7
8
9
10
11
12
13
// 第一阶段操作
// 对行 i = 1 到 n-1, 翻转子数组 [i, n]
for (int i = 1; i < n; ++i) {
std::cout << i << " " << i << " " << n << std::endl;
}

// 第二阶段操作
// 对行 j = 2 到 n, 翻转子数组 [1, j-1]
// 为了让最终矩阵和上面推导的一致,我们倒序循环
for (int i = 1; i < n; ++i) {
// 操作第 n-i+1 行, 翻转 [1, n-i]
std::cout << (n - i + 1) << " " << 1 << " " << (n - i) << std::endl;
}

AC代码

心路历程(WA,TLE,MLE……)

思路讲解

图论建模,拓扑排序。

拓扑排序的代码(使用BFS kahn‘s算法),通过判断q的大小可以知道其是不是严格的(该题目要求严格的顺序)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
ll trop(const vector<ll> &a,ll siz){
vector<ll> op=a;
Ans.clear();
queue<ll> q;
ll ret=3; // 3成功 2不能确定 1冲突
FOR(i,'A','Z'){
if(vis[i] && op[i]==0) q.push(i),Ans.pb(i);
}
if(SZ(q)>1) ret=2;
while(!q.empty()){
if(SZ(q)>1) ret=2;
ll node=q.front();q.pop();
ll cnt=0;
FOR(i,0,SZ(g[node])-1){
ll lnode=g[node][i];
op[lnode]-=1;
if(op[lnode]==0){
q.push(lnode);
Ans.pb(lnode);
}
}
}
if(SZ(Ans)==siz){
if(SZ(Ans)<N){ // 还没完全确定
return 2;
}else{
return ret;
}
}else{ // 说明有环
return 1;
}
}

AC代码

https://www.luogu.com.cn/record/220236107

心路历程(WA,TLE,MLE……)

思路讲解

检查点之间共有 mm 条单向通道。第 ii 条通道允许从点 sis_i 移动到点 tit_isi<tis_i < t_i),但不允许反方向移动。此外,只有当机器人至少拥有 wiw_i 个充电电池时,才能使用第 ii 条通道;否则,它将在途中耗尽电量。

这个 si<tis_i < t_i 尤为关键,这说明了这张图是有向无环图(DAG)。

那么二分做法不用多说,使用天然的拓扑排序以及类似dp做法解决,然后注意斜体加粗部分。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
inline bool check(ll mid){
FOR(i,0,N+5){Mxb[i]=0;}
FOR(i,1,N){
if(i!=1 && Mxb[i]==0) continue;
FOR(j,0,SZ(g[i])-1){
ll v=g[i][j][0],w=g[i][j][1];
if(min(mid,Mxb[i]+B[i])>=w){
Mxb[v]=max(Mxb[v],Mxb[i]+B[i]);
Mxb[v]=min(Mxb[v],mid);
}
}
}
if(Mxb[N]==0) return false;
return true;
}

AC代码

https://codeforces.com/contest/2110/submission/324044393

心路历程(WA,TLE,MLE……)

TLE,该代码一个点被访问多次,那么其所有边都将重新遍历一次。

image

思路讲解

题目总结

这是一道关于无人机通过障碍门的问题。有 N 道门,每道门都有高度范围 [l_i, r_i]。无人机初始高度为 0,每次可以选择保持高度不变或上升 1 个单位。部分门的操作已经固定(0 表示保持不变,1 表示上升),部分门的操作待定(-1 表示可以自由选择)。需要判断是否存在合法方案使无人机能通过所有门,如果存在则输出一种方案,否则输出 -1。

虽然这种题不是不可能dp,但dp不太可能。

容易想到一种贪心,在每一道门前尽量增加高度,

但是要注意这个高度的上界是什么。

1
2
3
4
5
6
7
8
9
10
11
12
// 在每一道门前尽量增加高度,但是要注意这个高度的上界是什么
ROF(i,N,1){
ll r=lr[i][1];
if(D[i]==1){
// 这里-1是因为这里当然不会判断,但是当mnR[i-1]来读这个mnR[i]的时候
// 我们希望mnR[i-1]的上界不能是mnR[i],因为+1就超了
// 连续操作与传递同理
mnR[i]=min(r-1,mnR[i+1]-1);
}else{
mnR[i]=min(r,mnR[i+1]);
}
}

这个上界不仅会受到后续最小 r 的影响,还会收到固定操作的影响

AC代码

https://codeforces.com/contest/2110/submission/323871174

心路历程(WA,TLE,MLE……)

思路讲解

注意到呢,把边固定下来,然后这个时候就只要去看简单路径了。因为走越多,遇到大的边的可能性越大。

当然,我们的下一步推进遇到了问题,这个问题不是树上问题,m 没有限定,那么 dp 就废了。

不过问题不大,容易想到如果不是树,我们能不能把它变为树?用最小生成树。

AC代码

AC

https://codeforces.com/contest/2117/submission/323773579

心路历程(WA,TLE,MLE……)