6.28 考试改题
P7424 [THUPC 2017] 天天爱射击
很经典的整体二分,注意正难则反。
另外需要精确地判断二分边界。
#include <bits/stdc++.h>
#define int long long
#define pb emplace_back
using namespace std;
const int N = 2e5 + 5;
int n, m, l[N << 1], r[N << 1], k[N << 1], x[N << 1], op[N << 1], ans[N << 1], res[N];
vector<int> start;
namespace BIT {
int t[N];
inline int lowbit(int x) {
return x & -x;
}
inline void add(int x, int k) {
for( ; x <= n ; x += lowbit(x))
t[x] += k;
return ;
}
inline int ask(int x) {
int res = 0;
for( ; x ; x -= lowbit(x))
res += t[x];
return res;
}
inline int query(int x, int y) {
return ask(y) - ask(x - 1);
}
}
using namespace BIT;
inline void solve(int L, int R, vector<int> q) {
if(q.empty()) return ;
if(L == R) {
for(auto i : q) ans[i] = L;
return ;
}
int mid = (L + R) >> 1;
vector<int> ql, qr;
for(auto i : q) {
if(op[i] == 1) {
if(i <= mid) {
ql.pb(i);
add(x[i], 1);
}
else qr.pb(i);
}
else {
int v = query(l[i], r[i]);
if(k[i] <= v) ql.pb(i);
else {
qr.pb(i);
k[i] -= v;
}
}
}
for(auto i : ql)
if(op[i] == 1) add(x[i], -1);
solve(L, mid, ql), solve(mid + 1, R, qr);
return ;
}
signed main() {
ios_base :: sync_with_stdio(NULL);
cin.tie(nullptr);
cout.tie(nullptr);
cin >> n >> m;
for(int i = 1 ; i <= n ; ++ i)
cin >> l[i + m] >> r[i + m] >> k[i + m];
for(int i = 1 ; i <= m ; ++ i)
cin >> x[i], op[i] = 1;
for(int i = 1 ; i <= n + m ; ++ i)
start.pb(i);
solve(0, m + 1, start);
for(int i = 1 ; i <= n + m ; ++ i)
if(! op[i]) ++ res[ans[i]];
for(int i = 1 ; i <= m ; ++ i)
cout << res[i] << '\n';
return 0;
}
CF1430E String Reversal
好像大家考试都过了这一题,但我实在是一点都没想到。
“交换邻项”这一操作,考虑从逆序对下手。
一个经典套路是将最终态下标赋予一个递增序列,然后将其和原先相同字符的位置一一对应。
因为是要操作次数最少,那么逆序对数也应该最少。即原序列应尽量保持递增。
那么按照这个思路贪心地操作即可。
#include <bits/stdc++.h>
#define int long long
#define pb emplace_back
using namespace std;
const int N = 2e5 + 5;
int n, a[N], p[N], pos[N], cnt[N];
vector<int> v[N];
string s;
namespace BIT {
int t[N];
inline int lowbit(int x) {
return x & -x;
}
inline void add(int x, int k) {
for( ; x <= n ; x += lowbit(x))
t[x] += k;
return ;
}
inline int query(int x) {
int res = 0;
for( ; x ; x -= lowbit(x))
res += t[x];
return res;
}
}
using namespace BIT;
inline int to(char ch) {
return ch - 'a' + 1;
}
signed main() {
ios_base :: sync_with_stdio(NULL);
cin.tie(nullptr);
cout.tie(nullptr);
cin >> n >> s;
s = " " + s;
for(int i = n ; i ; -- i) {
p[i] = n - i + 1;
v[to(s[i])].pb(p[i]);
++ cnt[to(s[i])];
}
for(int i = 1 ; i <= n ; ++ i)
a[i] = v[to(s[i])][pos[to(s[i])] ++];
int ans = 0;
// cerr << "!";
for(int i = n ; i ; -- i) {
// cerr << "!";
// cerr << a[i];
ans += query(a[i] - 1);
add(a[i], 1);
}
cout << ans;
return 0;
}