标签:连通 end test arc lse 依次 summary 大于 pac
双指针维护一个区间搞一下就行。
Code
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N = 1e5 + 5;
int n, k;
int a[N];
int main() {
ios::sync_with_stdio(false); cin.tie(0);
cin >> n >> k;
for(int i = 1; i <= n; i++) cin >> a[i];
int p = lower_bound(a + 1, a + n + 1, 0) - a - 1;
int left = max(1, p - k + 1);
int ans = INF;
while(left <= p + 1) {
int right = left + k - 1;
if(right > n) break;
if(a[right] < 0) {
ans = min(ans, -a[left]);
} else if(a[left] > 0) {
ans = min(ans, a[right]);
} else {
int res = -a[left];
ans = min(ans, min(2 * res + a[right], 2 * a[right] + res));
}
++left;
}
cout << ans;
return 0;
}
题意:
给出\(n\)个数,求所有区间中位数的中位数。
思路:
设最终答案为\(ans\)。
可以发现\(ans\)具有单调性,什么样的单调性呢?
假设中位数大于\(ans\)的区间有\(y\)个,发现随着\(ans\)的增大,\(y\)是单调不增的,所以我们就可以这样来搞。
具体做法:
细节见代码:(真是巧妙啊QAQ)
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 5;
int a[N], b[N];
int n;
int c[N];
int lowbit(int x) {return x & (-x);}
void add(int x, int v) {
for(; x < N; x += lowbit(x)) c[x] += v;
}
int query(int x) {
int ans = 0;
for(; x; x -= lowbit(x)) ans += c[x];
return ans;
}
bool check(int x) {
b[0] = 0;
for(int i = 1; i <= n; i++) {
if(a[i] < x) b[i] = -1;
else b[i] = 1;
b[i] += b[i - 1];
}
int Min = *min_element(b, b + n + 1);
if(Min <= 0) for(int i = 0; i <= n; i++) b[i] -= Min - 1;
ll tot = 0;
for(int i = 0; i <= n; i++) {
tot += query(b[i]);
add(b[i], 1);
}
for(int i = 0; i <= n; i++) add(b[i], -1);
return tot >= (1ll * (n + 1) * n / 2 + 1) / 2;
}
int main() {
ios::sync_with_stdio(false); cin.tie(0);
cin >> n;
for(int i = 1; i <= n; i++) cin >> a[i];
int l = 1, r = 1e9 + 1, mid;
while(l < r) {
mid = (l + r) >> 1;
if(check(mid)) l = mid + 1;
else r = mid;
}
cout << l - 1;
return 0;
}
题意:
给出一颗有偶数个点的树,现在问有多少种方案,能够将这些点两两配对并且每一条边都能被至少一对点对的路径经过。
思路:
感觉很神奇吧,独立做感觉很难做出来= =
Code
#include <bits/stdc++.h>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
//#define Local
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int N = 5005, MOD = 1e9 + 7;
int n;
struct Edge{
int v, next;
}e[N << 1];
int head[N], tot;
void adde(int u, int v) {
e[tot].v = v; e[tot].next = head[u]; head[u] = tot++;
}
ll g[N];
void init() {
g[0] = 1;
for(int i = 2; i < N; i += 2) g[i] = g[i - 2] * (i - 1) % MOD;
}
ll f[N][N], sz[N], tmp[N];
void dfs(int u, int fa) {
f[u][sz[u] = 1] = 1;
for(int i = head[u]; ~i; i = e[i].next) {
int v = e[i].v;
if(v == fa) continue;
dfs(v, u);
for(int j = 0; j <= sz[u] + sz[v]; j++) tmp[j] = f[u][j], f[u][j] = 0;
for(int j = 1; j <= sz[u]; j++) {
for(int k = 0; k <= sz[v]; k++) {
(f[u][j + k] += (tmp[j] * f[v][k]) % MOD) %= MOD;
}
}
sz[u] += sz[v];
}
for(int i = 2; i <= sz[u]; i += 2) {
f[u][0] -= (f[u][i] * g[i] % MOD);
f[u][0] %= MOD;
}
if(f[u][0] < 0) f[u][0] += MOD;
}
void run() {
for(int i = 1; i <= n; i++) head[i] = -1; tot = 0;
for(int i = 1; i < n; i++) {
int u, v; cin >> u >> v;
adde(u, v); adde(v, u);
}
dfs(1, 0);
cout << (MOD - f[1][0]) % MOD << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cout << fixed << setprecision(20);
#ifdef Local
freopen("../input.in", "r", stdin);
freopen("../output.out", "w", stdout);
#endif
init();
while(cin >> n) run();
return 0;
}
题意:
数轴上有\(n\)个点,\(m\)个出口,之后可以让所有点左移或者右移一格,若遇到出口点就消失。
最后问当所有点消失时,能够用到的出口总数。
思路:
感觉在折线上\(dp\)这种题挺有意思的,细节也比较多。还需要仔细品味一下。
详见代码:
Code
#include <bits/stdc++.h>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define INF 0x3f3f3f3f
//#define Local
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int N = 1e5 + 5, MOD = 1e9 + 7;
int n, m;
int x[N], y[N], d[N];
struct Point{
int a, b;
bool operator < (const Point& A) const {
if(a == A.a) return b > A.b;
return a < A.a;
}
}p[N];
int c[N];
int lowbit(int x) {return x & (-x);}
void add(int x, int v) {
for(; x < N; x += lowbit(x)) c[x] = (c[x] + v) % MOD;
}
int query(int x) {
int ans = 0;
for(; x > 0; x -= lowbit(x)) ans = (ans + c[x]) % MOD;
return ans;
}
void run() {
d[0] = 0;
memset(c, 0, sizeof(c));
for(int i = 1; i <= n; i++) cin >> x[i];
for(int i = 1; i <= m; i++) cin >> y[i];
int cnt = 0;
for(int i = 1; i <= n; i++) {
if(x[i] > y[1] && x[i] < y[m]) {
int left = lower_bound(y + 1, y + m + 1, x[i]) - y - 1;
int right = left + 1;
int l = x[i] - y[left], r = y[right] - x[i];
p[++cnt] = {l, r};
d[++d[0]] = r;
}
}
sort(d + 1, d + d[0] + 1);
d[0] = unique(d + 1, d + d[0] + 1) - d - 1;
for(int i = 1; i <= cnt; i++) {
p[i].b = lower_bound(d + 1, d + d[0] + 1, p[i].b) - d;
}
sort(p + 1, p + cnt + 1);
int ans = 1;
for(int i = 1; i <= cnt; i++) {
if(p[i].a == p[i - 1].a && p[i].b == p[i - 1].b) continue;
int res = query(p[i].b - 1) + 1;
if(res >= MOD) res -= MOD;
add(p[i].b, res);
ans = (ans + res) % MOD;
}
cout << ans << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cout << fixed << setprecision(20);
#ifdef Local
freopen("../input.in", "r", stdin);
freopen("../output.out", "w", stdout);
#endif
while(cin >> n >> m) run();
return 0;
}
标签:连通 end test arc lse 依次 summary 大于 pac
原文地址:https://www.cnblogs.com/heyuhhh/p/11569690.html