【LGR-049】洛谷7月月赛
比赛开始一个小时才想起来QwQ,当场写了ABC
#A: P4752 Divided Prime
日常送分题 注意只留一个非1数判他是不是质数
#B: P4753 River Jumping
题意:有跳跃距离下限,求能否经过所有石头恰好一次跳一个来回
贪心
首先距离河岸最近的两个石头必须要能跳上,剩下最多的隔一个跳一个(因为是来回)
#C: P4754 True Vegetable
经典的二分+贪心
二分最小回合数,把所有菜气都减去,然后从左到右贪心加,bit维护
一开始以为r值没用,原来r值保证了答案的单调性
#D: P4755 Beautiful Pair
题意:小D有个数列 \({a}\) ,当一个数对 \((i,j)(i≤j)\) 满足 \(a_i*a_j \le \max(a_i,a_{i+1},…,a_j)\) ,小D认为这个数对是美丽的.请你求出美丽的数对的数量。
单调栈处理出每个值作为最大值的长度a_x [l,r]
然后对于[l,x]中每个值\(a_i\),找[x,r]中满足\(a_j \le \frac{a_x}{a_i}\)的数量,这里可以用主席树实现
但这样复杂度不对,可以选长度短的一段来枚举
复杂度 \(T(n) = T(a) + T(n-a-1) + O(n\log n) = O(n\log^2 n),其中a \le n/2\)
问了一下,可以数归证明。其实就是启发式合并
//D
#include
#include
#include
#include
using namespace std;
const int N = 1e5+5;
int n, a[N], mp[N], m;
int st[N], top, l[N], r[N];
void init() {
for(int i=1; i<=n; i++) {
int le = i;
while(top && a[st[top]] <= a[i]) {
le = l[st[top]];
r[st[top]] = i-1;
top--;
}
st[++top] = i;
l[i] = le;
}
while(top) r[st[top--]] = n;
sort(mp+1, mp+1+n);
m = unique(mp+1, mp+1+n) - mp - 1;
}
struct node {
int lc, rc, size;
} t[N*18];
int sz, root[N];
void ins(int &x, int l, int r, int p) {
t[++sz] = t[x]; x = sz;
t[x].size ++;
if(l == r) return;
int mid = (l+r) >> 1;
if(p <= mid) ins(t[x].lc, l, mid, p);
else ins(t[x].rc, mid+1, r, p);
}
int que(int x, int y, int l, int r, int ql, int qr) {
if(mp[r] < ql || qr < mp[l]) return 0;
if(ql <= mp[l] && mp[r] <= qr) return t[y].size - t[x].size;
int mid = (l+r) >> 1, ans = 0;
if(ql <= mp[mid]) ans += que(t[x].lc, t[y].lc, l, mid, ql, qr);
if(mp[mid] < qr) ans += que(t[x].rc, t[y].rc, mid+1, r, ql, qr);
return ans;
}
long long ans;
void solve(int l1, int r1, int l2, int r2, int mid) {
for(int i=l1; i<=r1; i++) {
int v = a[mid] / a[i];
ans += que(root[l2-1], root[r2], 1, m, 1, v);
}
}
int main() {
freopen("in", "r", stdin);
ios::sync_with_stdio(false); cin.tie(); cout.tie();
cin >> n;
for(int i=1; i<=n; i++) cin >> a[i], mp[i] = a[i];
init();
//for(int i=1; i<=n; i++) printf("hi %d [%d %d]\n", i, l[i], r[i]);
for(int i=1; i<=n; i++) {
int x = lower_bound(mp+1, mp+1+m, a[i]) - mp;
root[i] = root[i-1];
ins(root[i], 1, m, x);
}
for(int i=1; i<=n; i++) {
int le = l[i], ri = r[i];
int d1 = i-le, d2 = ri-i;
//if(d1 == 0 || d2 == 0) continue;
if(d1 <= d2) solve(le, i, i, ri, i);
else solve(i, ri, le, i, i);
}
cout << ans;
}
//A
#include
#include
#include
#include
#include
typedef long long ll;
using namespace std;
const int N = 1e5+5;
int n, m, c[N];
ll a[N], b[N], mp[N];
bool is_p(ll n) {
for(ll i=2; i*i<=n; i++) if(n%i == 0) return false;
return true;
}
int main() {
freopen("in", "r", stdin);
ios::sync_with_stdio(false);
int T;
cin >> T;
while(T--) {
mp[0] = 0;
memset(c, 0, sizeof(c));
cin >> n >> m;
for(int i=1; i<=n; i++) cin >> a[i], mp[i] = a[i];
sort(mp+1, mp+1+n);
mp[0] = unique(mp+1, mp+1+n) -mp -1;
for(int i=1; i<=n; i++) {
int x = lower_bound(mp+1, mp+1+mp[0], a[i]) - mp;
c[x]++;
}
for(int i=1; i<=m; i++) {
cin >> b[i];
int x = lower_bound(mp+1, mp+1+mp[0], b[i]) - mp;
c[x]--;
}
int cnt = 0;
ll ans = 0;
for(int i=1; i<=mp[0]; i++) if(mp[i] != 1 && c[i]) {
cnt+=c[i];
ans = mp[i];
}
if(cnt!=1) puts("NO");
else if(!is_p(ans)) puts("NO");
else puts("YES");
}
}
//B
#include
#include
#include
#include
#include
#include
typedef long long ll;
using namespace std;
const int N = 1e5+5;
int n, m, s, x[N], vis[N];
vector v;
bool solve() {
int now = 0;
if(x[1] < s) return false;
now = 1; vis[1] = 1; v.push_back(1);
while(now+2 <= m) {
if(x[now+2] - x[now] < s) return false;
vis[now+2] = 1; v.push_back(now+2);
now += 2;
}
if(now == m-1) {
if(x[m] - x[now] < s) return false;
vis[m] = 1; v.push_back(m);
now ++;
}
for(int i=m-1; i>=0; i--) if(!vis[i]) {
if(x[now] - x[i] < s) return false;
now = i; v.push_back(i);
}
return true;
}
int main() {
freopen("in", "r", stdin);
ios::sync_with_stdio(false);
cin >> n >> m >> s;
for(int i=1; i<=m; i++) cin >> x[i];
x[0] = 0; x[++m] = n;
if(!solve()) cout << "NO" << endl;
else {
cout << "YES" << endl;
for(int i=0; i
//C
#include
#include
#include
#include
#include
#include
typedef long long ll;
using namespace std;
const int N = 6e5+5;
int n, m, k, L, a[N], A[N], r[105], w[N], x[N], v[N];
int c[N];
inline void add(int p, int v) { //printf("add %d %d\n", p, v); cout << endl;
for(; p<=n; p+=p&-p) c[p] += v;
}
inline int sum(int p) {
int ans = 0;
for(; p; p-=p&-p) ans += c[p];
return ans;
}
inline void add(int l, int r, int v) {
add(l, v);
add(r+1, -v);
}
bool check(int mid) { //printf("check %d\n", mid);
for(int i=1; i<=n; i++) a[i] = A[i];
for(int p = 1; p <= m && w[p] <= mid; p++) a[x[p]] -= v[p];
memset(c, 0, sizeof(c));
for(int i=n; i>=1; i--) a[i] -= a[i-1];
for(int i=1; i<=n; i++) add(i, a[i]);
int ans = 0;
for(int i=1; i<=n; i++) {
int x = sum(i); //printf("hi %d %d\n", i, x);
if(x < 1) add(i, i+k-1, 1-x), ans += 1-x;
}
//printf("ans %d\n", ans);
return ans <= mid;
}
int main() {
freopen("in", "r", stdin);
ios::sync_with_stdio(false);
cin >> n >> m >> k >> L;
for(int i=1; i<=n; i++) cin >> A[i];
for(int i=1; i<=L; i++) cin >> r[i];
for(int i=1; i<=m; i++) cin >> w[i] >> x[i] >> v[i];
int l = 0, r = 1e8, ans = 0;
while(l <= r) { //printf("erfen %d %d\n", l, r);
int mid = (l+r) >> 1;
if(check(mid)) ans = mid, r = mid-1;
else l = mid+1;
}
cout << ans;
}