HDU 4866 슈팅 문제 풀이: 주석 트 리
사격 목표 수량 ≥ 중합 수량: 전부 추가
사격 목표 수량 ≤ 중합 수량: 거리 만 증가 * 사격 목표 수량
그러나 이 문제 의 메모 리 는 양심 적 이 고 전체적으로 물 을 비교 해 보 자.
주요 방법 은 가로 좌표 1 ~ x 에 따라 주석 나 무 를 만 드 는 것 이다. 모든 주석 나 무 는 l, r 구간 의 설계 목표 수량 과 이런 수량 이 모두 사격 을 받 아 얻 은 점 수 를 유지 하 는 것 이다. 이런 것들 은 나 무 를 만 들 때 잘 유지 된다.
그 다음 에 이 라인 에 대한 처 리 는 스캐닝 라인 의 사상 으로 (왼쪽 점) 하나의 (+ 1) 입 점 을 구축 하고 (오른쪽 점 + 1) 의 위치 에 (- 1) 출 점 을 만 든 다음 에 왼쪽 에서 오른쪽으로 한 번 스 캔 하면 된다.
구체 적 인 과정 은 코드 참조:
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
#define INF 2*0x3f3f3f3f
using namespace std;
int n, m, x, p;
struct N { int ls, rs, w; long long sum; } tree[6000100];
int roots[200010];
int b[200010], tot, cnt;
int build_tree(int l, int r) {
int newnode = tot++;
tree[newnode].w = 0;
tree[newnode].sum = 0;
if (l != r) {
int mid = (l + r) / 2;
tree[newnode].ls = build_tree(l, mid);
tree[newnode].rs = build_tree(mid + 1, r);
}
return newnode;
}
int updata(int rt, int pos, int val) {
int newnode = tot++, tmp = newnode;
long long add = b[pos - 1];
tree[newnode].sum = tree[rt].sum + add * val;
tree[newnode].w = tree[rt].w + val;
int l = 1, r = cnt;
while (l < r) {
int mid = (l + r) / 2;
if (pos <= mid) {
tree[newnode].ls = tot++;
tree[newnode].rs = tree[rt].rs;
newnode = tree[newnode].ls;
rt = tree[rt].ls;
r = mid;
}
else {
tree[newnode].ls = tree[rt].ls;
tree[newnode].rs = tot++;
newnode = tree[newnode].rs;
rt = tree[rt].rs;
l = mid + 1;
}
tree[newnode].sum = tree[rt].sum + add * val;
tree[newnode].w = tree[rt].w + val;
}
return tmp;
}
long long query(int rt, int k) {
//printf("rt = %d k = %d
",rt,k);
int l = 1, r = cnt;
long long ans = 0;
while (l < r) {
int mid = (l + r) / 2;
int tmp = tree[tree[rt].ls].w;
if (tmp >= k) {
rt = tree[rt].ls;
r = mid;
}
else {
k -= tmp;
ans += tree[tree[rt].ls].sum;
rt = tree[rt].rs;
l = mid + 1;
}
}
if (tree[rt].w != 0)
ans += tree[rt].sum / tree[rt].w * min(k, tree[rt].w);
return ans;
}
struct P {
int x, y, val;
P() {}
P(int _x, int _y, int _val) : x(_x), y(_y), val(_val) {}
bool operator < (const P &rhs) const {
return x < rhs.x;
}
} pois[500010];
void print(int rt, int l = 1, int r = cnt) {
printf("l = %d r = %d w = %d sum = %I64d
", l, r, tree[rt].w, tree[rt].sum);
if (l != r) {
int mid = (l + r) / 2;
print(tree[rt].ls, l, mid);
print(tree[rt].rs, mid + 1, r);
}
}
int main() {
//freopen("in.in", "r", stdin);
//freopen("out.out", "w", stdout);
while (scanf("%d %d %d %d", &n, &m, &x, &p) != EOF) {
int l1, l2, d;
int ps = 0;
for (int i = 0; i < n; i++) {
scanf("%d %d %d", &l1, &l2, &d);
b[i] = d;
pois[ps++] = P(l1, d, 1);
pois[ps++] = P(l2 + 1, d, -1);
}
sort(b, b + n);
cnt = unique(b, b + n) - b;
sort(pois, pois + ps);
tot = 0;
roots[0] = build_tree(1, cnt);
int t = 0;
for (int i = 1; i <= x; i++) {
roots[i] = roots[i - 1];
while (t < ps && pois[t].x == i) {
int tmp = (int)(lower_bound(b, b + cnt, pois[t].y) - b) + 1;
roots[i] = updata(roots[i], tmp, pois[t].val);
t++;
}
}
/*
for (int i = 1; i <= x; i++) {
printf("**********************tree %d is :
", i);
print(roots[i]);
}
*/
long long now = 1;
int xs, as, bs, cs;
for (int i = 0; i < m; i++) {
//printf("i = %d
", i);
scanf("%d %d %d %d", &xs, &as, &bs, &cs);
long long tmp = query(roots[xs], (now * as + bs) % cs);
if (now > p) tmp *= 2;
printf("%I64d
", tmp);
now = tmp;
}
}
return 0;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
물체 검출의 평가 지표 IoU의 계산 방법Yolo나 SSD 등 물체 검출에서 평가 지표로 사용되는 IoU에 대해 조사했으므로 정리했습니다. IoU (Intersection over Union)는 두 영역이 얼마나 겹치는지를 나타내는 지표입니다. 두 영역의 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.