已AC:C,D,E,F
很喜欢这场比赛的题目风格。而且也不难。
C.Vasya And Array
题目大意:
给你 m m m条两类限制:区间 [ L , R ] [L,R] [L,R]单调非降 / 区间 [ L , R ] [L,R] [L,R]不符合单调非降.
问你是否能够找到一种符合所有限制的长度为 n n n的序列 a i a_i ai
n , m ≤ 1000 n,m \leq 1000 n,m≤1000
题目思路:思维,贪心
我们考虑一个位置一个位置的填。然后从前往后考虑每对相邻的数 ( i , i + 1 ) (i,i+1) (i,i+1).如果他们被完整的被包含在第一种条件限制中,那么这两个数必须要增。否则我们让他递减(贪心).因为我们是先满足条件1的限制,之后再暴力 c h e c k check check条件二.所以在满足条件1的情况下,我们想让序列尽量不增,这样好满足条件2.
想到这一点这题就很好做了. O ( n 2 ) O(n^2) O(n2)暴力搞即可。
AC代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define vi vector<int>
#define vl vector<ll>
const int maxn = 1000 + 5;
const int mod = 1e9 + 7;
int a[maxn];
struct No{
int l , r;};
vector<No> t[2];
bool check (int l , int r)
{
for (auto g : t[0])
if (g.l <= l && r <= g.r) return true;
return false;
}
int main()
{
ios::sync_with_stdio(false);
int n , m; cin >> n >> m;
for (int i = 1 ; i <= m ; i++){
int x , y , z; cin >> x >> y >> z;
x = !x;
t[x].pb({
y , z});
}
a[1] = 1005;
for (int i = 2 ; i <= n ; i++){
if (check(i - 1 , i)) a[i] = a[i - 1] + 1;
else a[i] = a[i - 1] - 1;
}
bool ok = true;
for (auto g : t[1]){
bool res = true;
for (int i = g.l ; i < g.r && res; i++){
if (a[i] > a[i + 1]) res = false;
}
if (res){
ok = false;
break;
}
}
if (!ok){
cout << "NO" << endl;
return 0;
}
cout << "YES" << endl;
for (int i = 1 ; i <= n ; i++){
cout << a[i] << " ";
}
cout << endl;
return 0;
}
进一步优化?
暴力check的部分我们用前缀最大值优化,复杂度降为 O ( n ) O(n) O(n).
D. Subarray Sorting
题目大意:
给你两个数组 a , b a,b a,b.你每次可以取 a a a的一个子数组,对其进行排序。问你是否能够将其转化为 b b b.
题目思路:
1.先判排序后 a = = b a==b a==b.
2.由于 b b b的顺序不一定是严格升序。而且一旦对一段排完序之后 大的就不能移动到小的之前 了。所以我们尽量对相邻两个数之间排序。例如:
a = [7,6,5]
b = [5,7,6]
3.由于要每一个位置上的数相同。那么我们简单的考虑从左往右一个一个匹配。循环b数组 1 到 i 1到i 1到i. p t r ptr ptr维护当前匹配到的 a a a数组的位置.
我们需要知道每个数的从小到大的位置。这个对值域开队列即可。对于 b i b_i bi,我们在 a a a找到离 i i i最近的位置 r r r.那么这个数能够被挪动到位置 i i i的条件是: [ i , r ] [i,r] [i,r]内最小值 = b i = b_i =bi.这个我们用线段树维护区间最小值.
挪动完之后,我们将 a r : = 1 e 9 a_r:=1e9 ar:=1e9。代表废除这个位置。 p t r ptr ptr不变.
启示:
面对这种需要多次挪动数组的某个数到最前面的问题,不用真的移动,而是用一个指针维护当前数组位置+将这个数改成 i n f inf inf(一个无效的数)来模拟这个问题。

AC代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define vi vector<int>
#define vl vector<ll>
#define tl (t << 1)
#define tr (t << 1 | 1)
#define mid ((l + r) >> 1)
const int maxn = 3e5 + 5;
const int mod = 1e9 + 7;
const int inf = 1e9;
int a[maxn] , b[maxn] , n;
int mi[maxn << 2];
void pushup(int t)
{
mi[t] = min(mi[tl] , mi[tr]);
}
void build (int t , int l , int r)
{
if (l == r) {
mi[t] = a[l];
return ;
}
build(tl , l , mid);
build(tr , mid + 1 , r);
pushup(t);
return ;
}
int ask (int t , int l , int r , int L , int R)
{
if (L <= l && r <= R) return mi[t];
int ans = 1e9;
if (L <= mid) ans = min(ans , ask(tl , l , mid , L , R));
if (R > mid) ans = min(ans , ask(tr , mid + 1 , r , L , R));
return ans;
}
void modify (int t , int l , int r , int p , int c)
{
if (l == r){
mi[t] = c;
return ;
}
if (p <= mid) modify(tl , l , mid , p , c);
else modify(tr , mid + 1 , r , p , c);
pushup(t);
return ;
}
int tmp[2][maxn];
bool check ()
{
for (int i = 1 ; i <= n ; i++) tmp[0][i] = a[i];
for (int i = 1 ; i <= n ; i++) tmp[1][i] = b[i];
sort(tmp[0] + 1 , tmp[0] + 1 + n);
sort(tmp[1] + 1 , tmp[1] + 1 + n);
for (int i = 1 ; i <= n ; i++) if (tmp[0][i] != tmp[1][i]) return false;
return true;
}
int main()
{
ios::sync_with_stdio(false);
int t; cin >> t;
while (t--){
cin >> n;
set<int> s[n + 2];
for (int i = 1 ; i <= n ; i++)
cin >> a[i] , s[a[i]].insert(i);
for (int i = 1 ; i <= n ; i++)
cin >> b[i];
if (!check()){
cout << "NO" << endl;
continue;
}
build(1 , 1 , n);
bool ok = true;
int ptr = 1;
for (int i = 1 ; i <= n ; i++){
while (a[ptr] == inf) ptr++;
int now = a[ptr];
if (b[i] == now) {
s[now].erase(ptr);
ptr++;
continue;
}
int r = *s[b[i]].begin();
if (ask(1 , 1 , n , ptr , r) != b[i]){
ok = false;
break;
}
modify(1 , 1 , n , r , inf);
a[r] = inf;
s[b[i]].erase(r);
}
cout << (ok ? "YES" : "NO") << endl;
}
return 0;
}
*/
E - Tree Painting,水题
题目大意:
让你确定一个根,使得各点深度之和相加最大.
题目思路:
换根计算即可.
F. Expected Square Beauty - 计数,期望
见:下一篇博客