训练网址
系列简介:选择了2019~2021年 ICPC, CCPC, 牛客杭电, 省赛校赛优质题目,目标做够100套题。
#include
#include
#include
#include
using namespace std;
const int maxn = 1000010;
int a[maxn];
struct node {
int l, r, maxc;
}tr[maxn * 2];
int N, C;
void pushup(int u) {
tr[u].maxc = max(tr[2 * u].maxc, tr[2 * u + 1].maxc);
}
void build(int u, int l, int r) {
if (l == r) {
tr[u] = { l, r, C };
}
else {
tr[u].l = l, tr[u].r = r;
int mid = (l + r) / 2;
build(2 * u, l, mid), build(2 * u + 1, mid + 1, r);
pushup(u);
}
}
bool modify(int u, int x) {
//printf("***\n");
if (tr[u].l == tr[u].r) {
tr[u].maxc -= x;
return true;
}
else {
if (tr[2 * u].maxc >= x && modify(2 * u, x)) {
pushup(u);
return true;
}
if (tr[2 * u + 1].maxc >= x && modify(2 * u + 1, x)) {
pushup(u);
return true;
}
return false;
}
}
int query(int u, int id) {
if (tr[u].l == tr[u].r) return tr[u].maxc;
int mid = (tr[u].l + tr[u].r) / 2;
if (id <= mid) return query(2 * u, id);
else if (id > mid) return query(2 * u + 1, id);
}
int main() {
int T;
scanf("%d", &T);
while (T--) {
scanf("%d%d", &N, &C);
build(1, 1, N);
for (int i = 1; i <= N; i++) {
scanf("%d", &a[i]);
}
map<int, int> mp;
int res1 = 0, res2 = 0;
for (int i = 1; i <= N; i++) {
modify(1, a[i]);
auto p = mp.lower_bound(a[i]);
if (p != mp.end()) {
--p->second;
++mp[p->first - a[i]];
if (p->second == 0) mp.erase(p);
}
else {
++mp[C - a[i]];
++res2;
}
}
for (int i = 1; i <= N; i++) {
//printf("$$$ %d\n", query(1, i));
if (query(1, i) == C) {
res1 = i - 1;
break;
}
if (i == N) {
res1 = N;
}
}
printf("%d %d\n", res1, res2);
}
return 0;
}
#include
#include
#include
using namespace std;
typedef long long ll;
const int maxn = 1010, maxm = 4000010;
char mz[maxn][maxn], str[maxn];
int N, M;
int son[maxm][26], w[maxm], idx;
void insert(char* str, int value) {
int p = 0;
for (int i = 0; str[i]; i++) {
int u = str[i] - 'a';
if (!son[p][u]) son[p][u] = ++idx;
p = son[p][u];
}
w[p] = value;
}
int query(char* str) {
int p = 0;
for (int i = 0; str[i]; i++) {
int u = str[i] - 'a';
if (!son[p][u]) return -1;
p = son[p][u];
}
//这个地方必须要这样写。
//也许输入的 str 是保存的某一个字符串的前缀,那么此时的 p 确实不是 0
//但是这样的前缀也许在字典树中不存在。
if (w[p]) return w[p];
else return -1;
}
void init() {
for (int i = 0; i <= idx; i++) {
fill(son[i], son[i] + 26, 0);
w[i] = 0;
}
idx = 0;
}
int main() {
int T;
scanf("%d", &T);
while (T--) {
init();
scanf("%d%d", &N, &M);
for (int i = 1; i <= N; i++) {
scanf("%s", mz[i] + 1);
}
while (M--) {
int x;
scanf("%s%d", str, &x);
insert(str, x);
}
ll ans = 0;
bool flag = true;
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
int sz = 0;
//这个判断得加上
if (mz[i][j] == '#') continue;
if (i == 1 || mz[i - 1][j] == '#') {
int x = i;
while (x <= N && mz[x][j] != '#') {
str[sz++] = mz[x][j];
x++;
}
str[sz] = 0;
int v = query(str);
if (v == -1) {
flag = false;
break;
}
ans += v;
}
//printf("*** %d %s %lld\n", sz, str, ans);
sz = 0;
if (j == 1 || mz[i][j - 1] == '#') {
int y = j;
while (y <= N && mz[i][y] != '#') {
str[sz++] = mz[i][y];
y++;
}
str[sz] = 0;
int v = query(str);
if (v == -1) {
flag = false;
break;
}
ans += v;
}
//printf("*** %d %s %lld\n", sz, str, ans);
}
if (!flag) break;
}
if (!flag) ans = -1;
printf("%lld\n", ans);
}
return 0;
}
#include
#include
#include
#include
#include
using namespace std;
const int maxn = 100010;
typedef long long ll;
int N, M, a[maxn];
ll sum2[maxn];
vector<int> nums;
struct node {
int l, r;
int cnt;
ll sum;
}tr[maxn * 4 + maxn * 17];
//空间开到 4N + N * log(N)
int root[maxn], idx;
int find(int x) {
return lower_bound(nums.begin(), nums.end(), x, greater<int>()) - nums.begin();
}
int build(int l, int r) {
int p = ++idx;
tr[p] = { l, r };
if (l == r) return p;
int mid = (l + r) / 2;
tr[p].l = build(l, mid), tr[p].r = build(mid + 1, r);
return p;
}
//p 为原来的线段树的结点,q 为复制的线段是的结点
int insert(int p, int l, int r, int x) {
int q = ++idx;
tr[q] = tr[p];
if (l == r) {
tr[q].cnt++;
tr[q].sum += nums[x];
return q;
}
int mid = (l + r) / 2;
if (x <= mid) tr[q].l = insert(tr[p].l, l, mid, x);
else tr[q].r = insert(tr[p].r, mid + 1, r, x);
tr[q].cnt = tr[tr[q].l].cnt + tr[tr[q].r].cnt;
tr[q].sum = tr[tr[q].l].sum + tr[tr[q].r].sum;
return q;
}
ll query(int q, int p, int l, int r, int k) {
//这个地方要小心,因为有重复数字的话,需要这样处理,不然结果会偏大。
if (l == r) return (tr[q].sum - tr[p].sum) / (tr[q].cnt - tr[p].cnt) * k;
int cnt = tr[tr[q].l].cnt - tr[tr[p].l].cnt;
int mid = (l + r) / 2;
if (k <= cnt) return query(tr[q].l, tr[p].l, l, mid, k);
else return tr[tr[q].l].sum - tr[tr[p].l].sum + query(tr[q].r, tr[p].r, mid + 1, r, k - cnt);
}
int main() {
for (ll i = 1; i <= 100000; i++) {
sum2[i] = i * i + sum2[i - 1];
}
int T;
scanf("%d", &T);
while (T--) {
//看看如何初始化的
nums.clear();
for (int i = 0; i <= idx; i++) {
tr[i] = { 0, 0, 0, 0 };
}
fill(root, root + N + 1, 0);
idx = 0;
scanf("%d", &N);
for (int i = 1; i <= N; i++) {
scanf("%d", &a[i]);
nums.push_back(a[i]);
}
sort(nums.begin(), nums.end(), greater<int>());
nums.erase(unique(nums.begin(), nums.end()), nums.end());
root[0] = build(0, nums.size() - 1);
for (int i = 1; i <= N; i++) {
root[i] = insert(root[i - 1], 0, nums.size() - 1, find(a[i]));
}
scanf("%d", &M);
while (M--) {
int l, r, k;
scanf("%d%d%d", &l, &r, &k);
int m = r - l + 1;
printf("%lld\n", sum2[m] + query(root[r], root[l - 1], 0, nums.size() - 1, k));
}
}
return 0;
}
#include
#include
#include
using namespace std;
const int maxn = 210;
int a[maxn], b[maxn];
double ans[maxn];
int N;
bool flag;
void Print() {
flag = true;
for (int i = 0; i < N; i++) {
//if(ans[i] == 0) printf("0%c", i + 1 == N ? '\n' : ' ');
printf("%.1f%c", ans[i], i + 1 == N ? '\n' : ' ');
}
}
int main() {
int T;
scanf("%d", &T);
while (T--) {
memset(a, 0, sizeof a);
memset(b, 0, sizeof b);
memset(ans, 0, sizeof ans);
scanf("%d", &N);
for (int i = 0; i <= N; i++) scanf("%d", &a[i]);
for (int i = 0; i <= N; i++) scanf("%d", &b[i]);
flag = false;
//先判断这个,后面可以省去一些讨论。
if (a[N] * b[N] < 0) Print();
else {
for (int i = 0; i < N; i++) {
if (a[i] * b[i] < 0) {
ans[i] = 10000;
Print();
break;
}
//考虑二次方程 (ax + b)(cx + d) < 0 有解的情况
else if(a[i] * b[i] > 0 && a[i] * b[N] != b[i] * a[N]){
ans[i] = (-(double)a[N] / a[i] - (double)b[N] / b[i]) / 2.0;
Print();
break;
}
else if ((a[i] != 0 || b[i] != 0) && a[i] * b[N] != b[i] * a[N]) {
if (a[i] == 0) swap(a, b);
if (a[i] * b[N] > 0) ans[i] = -10000;
else if (a[i] * b[N] < 0) ans[i] = 10000;
else continue;
Print();
break;
}
}
}
if (!flag) printf("No\n");
}
return 0;
}
#include
#include
#include
#include
#include
#define x first
#define y second
const double eps = 1e-8, INF = 1e12;
using namespace std;
const int maxn = 510;
typedef pair<double, double> P;
int sign(double x) {
if (fabs(x) < eps) return 0;
if (x < 0) return -1;
return 1;
}
P operator + (P a, P b) {
return { a.x + b.x, a.y + b.y };
}
P operator -(P a, P b) {
return { a.x - b.x, a.y - b.y };
}
P operator*(P a, double t) {
return { a.x * t, a.y * t };
}
double operator*(P a, P b) {
return a.x * b.x + a.y * b.y;
}
double cross(P a, P b) {
return a.x * b.y - b.x * a.y;
}
P get_line_intersection(P p, P v, P q, P w) {
P u = p - q;
double t = cross(w, u) / cross(v, w);
return p + v * t;
}
bool on_segment(P p, P a, P b) {
return sign(cross(p - a, p - b)) == 0 && sign((p - a) * (p - b)) <= 0;
}
int N, M;
P stars[maxn], end1[maxn], end2[maxn];
bool on_cloud[maxn];
void merge(vector<P>& v1, vector<P>& v2) {
sort(v1.begin(), v1.end());
int sz = v1.size();
if (sz == 0) return;
double st = v1[0].x, ed = v1[0].y;
for (int i = 1; i < sz; i++) {
if (v1[i].x > ed) {
v2.push_back({ st, ed });
st = v1[i].x, ed = v1[i].y;
}
else ed = max(ed, v1[i].y);
}
v2.push_back({ st, ed });
}
double solve() {
memset(on_cloud, 0, sizeof on_cloud);
//预处理出星星在云中的情况
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= M; j++) {
on_cloud[i] |= on_segment(stars[i], end1[j], end2[j]);
on_cloud[i] |= (!sign(stars[i].x - end1[j].x) && !sign(stars[i].y - end1[j].y));
on_cloud[i] |= (!sign(stars[i].x - end2[j].x) && !sign(stars[i].y - end2[j].y));
}
//printf("*** %d\n", on_cloud[i]);
}
vector<P> segs;
for (int i = 1; i <= N; i++) {
vector<P> shadows;
double left = -INF, right = INF;
for (int j = 1; j <= M; j++) {
P o = { 0, 0 }, vec = { 1, 0 };
double l, r;
if (on_cloud[i]) l = -INF, r = INF;
//三种位置关系
else if (stars[i].y <= end1[j].y) {
l = r = 0;
}
else if (stars[i].y <= end2[j].y) {
auto p = get_line_intersection(stars[i], end1[j] - stars[i], o, vec);
//小心这个地方,很长时间才发现,不是比较光源和上面的点那个纵坐标大,而是比较光源在直线的左边还是右边。
if (cross(end1[j] - stars[i], end2[j] - stars[i]) < 0) l = -INF, r = p.x;
else l = p.x, r = INF;
}
else {
auto p1 = get_line_intersection(stars[i], end1[j] - stars[i], o, vec);
auto p2 = get_line_intersection(stars[i], end2[j] - stars[i], o, vec);
l = p1.x, r = p2.x;
if (l > r) swap(l, r);
}
shadows.push_back({ l, r });
//if(i == 8) printf("### %d %d %f %f\n", i, j, l, r);
}
vector<P> new_shadows;
merge(shadows, new_shadows);
int sz = new_shadows.size();
/*for (auto p : new_shadows) {
printf("$$$ %f %f\n", p.x, p.y);
}*/
if (sz == 0) {
segs.push_back({ -INF, INF });
continue;
}
if (sign(new_shadows[0].x + INF)) segs.push_back({ -INF, new_shadows[0].x });
for (int i = 1; i < sz; i++) segs.push_back({ new_shadows[i - 1].y, new_shadows[i].x });
if (sign(new_shadows[sz - 1].y - INF)) segs.push_back({ new_shadows[sz - 1].y, INF });
/*if(!segs.empty())printf("&&& %f %f\n", segs.back().x, segs.back().y);*/
}
vector<P> new_segs;
merge(segs, new_segs);
double res = 0;
int sz = new_segs.size();
if (sz == 0) return -1;
/*for (auto p : new_segs) {
printf("*** %f %f\n", p.x, p.y);
}*/
if (sign(new_segs[0].x + INF)) return -1;
if (sign(new_segs[sz - 1].y - INF)) return -1;
for (int i = 1; i < sz; i++) res += new_segs[i].x - new_segs[i - 1].y;
if (res >= 1e9) return -1;
return res;
}
int main() {
int T;
scanf("%d", &T);
while (T--) {
scanf("%d%d", &N, &M);
for (int i = 1; i <= N; i++) {
scanf("%lf%lf", &stars[i].x, &stars[i].y);
}
for (int i = 1; i <= M; i++) {
scanf("%lf%lf%lf%lf", &end1[i].x, &end1[i].y, &end2[i].x, &end2[i].y);
//规定让 end2 在上面
if (end1[i].y > end2[i].y) swap(end1[i], end2[i]);
}
printf("%.10f\n", solve());
}
return 0;
}
#include
#include
#include
#include
using namespace std;
const int maxn = 100010;
int p[maxn], sz[maxn];
int find(int x) {
if (p[x] == x) return x;
return p[x] = find(p[x]);
}
void unite(int a, int b) {
if (find(a) == find(b)) return;
sz[find(b)] += sz[find(a)];
p[find(a)] = find(b);
}
int main() {
int T;
scanf("%d", &T);
while(T--){
int N;
scanf("%d", &N);
for (int i = 1; i <= N; i++) {
p[i] = i, sz[i] = 1;
}
unordered_map<int, int> um;
int id = 0;
for (int i = 1; i <= N; i++) {
int a, b;
scanf("%d%d", &a, &b);
if (!um.count(a)) um[a] = ++id;
if (!um.count(b)) um[b] = ++id;
unite(um[a], um[b]);
}
int ans = 0;
for (int i = 1; i <= N; i++) {
ans = max(ans, sz[i]);
}
printf("%d\n", ans);
}
return 0;
}