0%

思路讲解

求解右边第一个大于自己的数的下标。

AC代码

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

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

思路讲解

就是问可以通过$ A_i=A_i \mod X$ 这个操作变的有序的子串有多少个?

那么注意到那,这个操作没有说那么不可控,其实就是可以变为[ 0,Aimod(Ai/2+1) ][\ 0,A_i \mod (A_i/2+1)\ ] 中的一个。

https://www.codechef.com/viewsolution/1166421088

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
	FOR(i,1,N){
ll idx=-1;
FOR(j,i,N){
ll val=A[j]%(A[j]/2+1);
// #ifdef LOCAL
// debug(A[j]);debug(val);
// #endif
if(val>idx){
++ans;
++idx;
}else if(A[j]>idx){ // we observe sometime we should not make the num modded
idx=A[j]; // such as test case 1
++ans;
}else{
break;
}
}
}

简单就套一个简单的O(n**2)就过了。困难要求线性复杂度,这个就比较难了。

那么我们试过了,双指针是不太能解决,因为左端点的移动不仅有可能造成右端点的变化,还有可能造成里面的变化,当然这个我们只要表征右端点就行了,但是会使得情况很复杂。

唉,读了很多遍题解,发现他应该是藏了一手,有些东西没说清楚。

upjjiupjjiup_j≥j-i \Rightarrow up_j-j \ge -i 因此我们就是要找到第一个不符合这个式子的数字。

不难发现我们可以用单调栈做这个 P5788 【模板】单调栈。

但是光解决上面的这个问题不够呀,所以我们需要一步,就是推导这个如果我不去删这个数,可以得到什么效果?如果说Ai<jiA_i<j-i,那么就不用管了,到头了。upjji+Aiupjji+Aiup_j\ge j-i+A_i \Rightarrow up_j-j\ge -i+A_i,那么我们也可以用一样的方法去解决。

AC代码

https://www.codechef.com/viewsolution/1166421088

加了一个记忆化搜索就好了。

https://www.codechef.com/viewsolution/1166895091

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

TLE,应该是被卡了。就是像下面这样走有的时候可能会导致退化为线性时间复杂度。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
FOR(i,1,N){
ll idx=fib[i],lab=idx-i;
while(idx<=N){
//
if(A[idx]<lab){
ans+=idx-i;
break;
}
ll oidx=idx;
idx=seb[idx];
lab=idx-oidx+A[oidx];
if(idx==N){
if(A[idx]<lab){
ans+=idx-i;
}else{
ans+=idx-i+1;
}
break;
}
}
}

思路讲解

https://www.codechef.com/viewsolution/1165824691

简单的后缀最大判断。

困难版的题意稍微有点难懂,但是总的来说就是你不是找出来一个M吗,这个最大格挡序列可不可以包含i?

那么代码分析我放在这个链接里了,反正都是chinglish,都是读的懂的。

https://www.codechef.com/viewsolution/1166105552

那么正向的贪心操作怎么样复制到这个逆向那?我认为这个是这道题目比较值得学习的点。

1
2
3
4
5
6
7
8
9
10
ROF(i,N,1){
if(opx+1>=B[i] && opx<X){
opx++;
++sans;
suf[i]=sans;
Ans[i]=true;
}else{
suf[i]=suf[i+1];
}
}

AC代码

https://www.codechef.com/viewsolution/1165824691

https://www.codechef.com/viewsolution/1166105552

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

思路讲解

codeChef题目可以看viewsolution,就是下面这个链接

1
2
3
4
5
6
7
8
9
10
11
inline ll diff(ll a,ll b){
if(a<=b) return 0;
bitset<32> ba(a); // 存储是正序的
bitset<32> bb(b);
ROF(i,31,0){
ll bai=ba[i],bbi=bb[i];
if(bai-bbi==1){
return 1<<i;
}
}
}

AC代码

https://www.codechef.com/viewsolution/1165814370

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

思路讲解

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

注意到,可以对称的操作,反转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……)