2018 CCPC 지 린 경기 지역 문제 풀이
100090 단어 데이터 구조 - 선분 트 리시합
#include
#define ll long long
using namespace std;
const int maxn = 2e5 + 10, mod = 1e9 + 7;
int main() {
int T, n, kase = 0;
cin>>T;
while (T--) {
cin>>n;
ll ans = 0;
for (int l = 1, r; l <= n; l = r + 1) {
r = n / (n / l);
ans += 1ll * (r - l + 1) * (n / l);
}
printf("Case %d: ", ++kase);
if (ans % 2)
puts("odd");
else
puts("even");
}
}
1002. 더 월 드 출석 체크
#include
#define ll long long
using namespace std;
const int maxn = 2e5 + 10;
string s, a, b, tp;
map<string, int> mp;
int gao(string tmp) {
if (tmp.length() == 5)
return (tmp[0] - '0') * 10 + tmp[1] - '0';
return tmp[0] - '0';
}
int main() {
int T, n, kase = 0;
mp["Beijing"] = 8;
mp["Washington"] = -5;
mp["London"] = 0;
mp["Moscow"] = 3;
cin>>T;
while (T--) {
cin>>s>>tp>>a>>b;
string res = "Today";
int time = gao(s);
if (time == 12)
time = 0;
if (tp == "PM")
time += 12;
time += mp[b] - mp[a];
if (time < 0) {
res = "Yesterday";
time += 24;
if (time >= 12) {
tp = "PM";
time -= 12;
}
else {
tp = "AM";
}
}
else if (time >= 24) {
res = "Tomorrow";
time -= 24;
if (time < 12)
tp = "AM";
else
tp = "PM";
}
else {
if (time >= 12)
tp = "PM", time -= 12;
else
tp = "AM";
}
if (!time)
time = 12;
string s2 = "";
if (time >= 10)
s2 += (time / 10 + '0');
s2 += (time % 10 + '0');
int pos = 2;
if (s.length() == 4)
pos--;
for (pos; pos < s.length(); pos++)
s2 += s[pos];
printf("Case %d: ", ++kase);
cout<<res<<" "<<s2<<" "<<tp<<endl;
}
}
1003. Justice
해법: 우선, 100000 보다 큰 ki 값 에 대해 우 리 는 관여 할 필요 가 없다. 만약 에 이 수의 총합 이 1 보다 크 면 반드시 해 가 있 을 것 이다. 우 리 는 먼저 이 수의 총합 이 1 보다 큰 지 판단 한다. 우 리 는 수조 vis 로 모든 수의 출현 횟수 를 통계 한 다음 에 큰 것 에서 작은 것 으로 x, vis [x] + = vis [x + 1] / 2 를 들 고 마지막 vis [0] 가 0 이 아니라면 조건 을 만족시킨다.두 번 째 단 계 는 우리 가 조합 합 니 다. 우 리 는 모든 값 이 20 보다 작은 ki 를 꺼 내 서 그들 을 모두 2 ^ (20 - ki) 로 만 든 다음 에 작은 매 거 진 숫자 에 이 르 러 이 숫자 들 이 2 ^ (19) 와 같 을 때 까지 이 숫자 들 을 1 로 표시 하고 나머지 는 모두 0 으로 표시 하면 됩 니 다.
#include
#define ll long long
using namespace std;
const int maxn = 1e5 + 10;
int a[maxn], p[21], vis[maxn], vis2[maxn], ans[maxn];
struct node {
int v, id;
bool operator<(const node &t) const {
return v < t.v;
}
} b[maxn];
int main() {
int T, kase = 0;
scanf("%d", &T);
p[0] = 1;
for (int i = 1; i <= 20; i++)
p[i] = p[i - 1] * 2;
while (T--) {
int n, mx = 0;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
ans[i] = 0;
if (a[i] >= 100000)
a[i] = 0;
vis[a[i]]++;
mx = max(mx, a[i]);
b[i] = node{a[i], i};
}
vis[0] = 0;
for (int i = 100000; i; i--)
if (vis[i])
vis[i - 1] += vis[i] / 2;
printf("Case %d: ", ++kase);
if (!vis[0]) {
for (int i = 1; i <= mx; i++)
vis[i] = 0;
puts("NO");
continue;
}
puts("YES");
ll res = 0;
sort(b + 1, b + 1 + n);
for (int i = 1; i <= n; i++)
if (b[i].v <= 20) {
int tmp = p[20 - b[i].v];
if (res + tmp <= p[19])
ans[b[i].id] = 1, res += tmp;
}
for (int i = 1; i <= n; i++)
if (a[i] >= 20)
printf("0");
else
printf("%d", ans[i]);
puts("");
for (int i = 1; i <= mx; i++)
vis[i] = 0;
}
}
1004. The Moon
해법: d [i] [j] 를 q 로 설정 하여 i 회 2%, j 회 1.5%, 즉 q = 0.02 + 0.02 * i + 0.015 * j 를 증가 시 켰 고 실패 할 확률 이 있 습 니 다. 우 리 는 다음 에 조작 에 성공 할 수 있 습 니 다. 그러면 ans + = d [i] * p * q * (i + j + 1), 다음 에 직접 몬스터 를 때 려 서 이기 지 못 했 을 수도 있 습 니 다. d [i] [j + 1] + d [i] * * (1 - p), 다음 에 도 몬스터 를 이 길 수 있 지만 당 첨 되 지 못 했 습 니 다. d [i + 1] [j]+ = d [i] [j] * p * (1 - q), 현재 q > 1 이 라면 계속 이동 하지 않 고 공헌 으로 계산 합 니 다. ans + = d [i] * (i + j) + d [i] / p.
#include
#define db double
#define ll long long
using namespace std;
db d[52][70];
int main() {
int T, kase = 0;
scanf("%d", &T);
while (T--) {
int x;
cin>>x;
db p = 0.01 * x, ans = 0.0;
for (int i = 0; i <= 50; i++)
for (int j = 0; j <= 70; j++)
d[i][j] = 0.0;
d[0][0] = 1.0;
for (int i = 0; i <= 49; i++) {
for (int j = 0; j <= 70; j++) {
db p1 = 0.02 + 0.02 * i + 0.015 * j;
if (p1 > 1.0) {
ans += d[i][j] * (i + j) + d[i][j] / p;
break;
}
ans += d[i][j] * (i + j + 1) * p * p1;
d[i + 1][j] += d[i][j] * p * (1.0 - p1);
d[i][j + 1] += d[i][j] * (1.0 - p);
}
}
printf("Case %d: %.10f
", ++kase, ans);
}
}
1006. The Hermit
제목: 각 점 i 에 대해 덮어 쓸 수 있 는 범 위 는 [i - ri + 1, i + ri - 1] 이 고 임의의 인접 점 i, i + 1, i + 1 의 덮어 쓸 수 있 는 왼쪽 경 계 는 반드시 i 가 덮어 쓰 는 왼쪽 경계 보다 크 며, 각 점 i 에 대해 서 는 합 법 적 인 k 의 수량 으로 정의 합 법 적 인 k: k < i, 그리고 k 는 i 의 덮어 쓰 는 범위 내 에 있 으 며, 점 j, k < j, 그리고 dist (k, j) 가 존재 합 니 다.> = dist (j, i), 그리고 i 와 k 는 모두 j 의 커버 범위 안에 있 습 니 다.각 점 의 가중치 가 다 르 거나 합 쳐 질 것 을 요구 하 다.
해법: 제목 의 뜻 이 매우 복잡 하 다. 제목 의 도둑 물 은 리 < 3 의 점 에 대해 분명히 가중치 가 0 이 고 리 > = 3 의 점 에 대해 우 리 는 제목 의 뜻 으로 리 - 1 이 덮 인 왼쪽 경 계 는 반드시 < = 리 가 덮 인 왼쪽 경 계 를 말한다. 즉, 나 는 j = i - 1 을 설정 하고 다른 i 왼쪽 이 덮 을 수 있 는 점 은 모두 합 법 적 인 k 점 으로 할 수 있다. 즉, i 의 가중치 가 리 - 2 이다.
#include
#define ll long long
using namespace std;
const int maxn = 1e6 + 10, N = 1e6;
int main() {
int T, kase = 0;
scanf("%d", &T);
while (T--) {
int n, x, ans = 0;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d", &x);
if (x >= 3)
ans ^= (x - 2);
}
printf("Case %d: %d
", ++kase, ans);
}
}
1008. Lovers
해법: 우 리 는 매번 조작 을 분리 하여 처리 합 니 다. tagR [o] 로 오른쪽 에 추 가 된 숫자 를 표시 합 니 다. R [o] 는 이 구간 오른쪽 에 숫자 를 추가 한 후의 총화 입 니 다. len [o] 는 이 구간 에 몇 번 을 추 가 했 습 니까? 우 리 는 표 시 를 보 냅 니 다. fa 노드 에 대한 정 보 는 o 노드 (o 노드 길이 가 n 이 라 고 가정 합 니 다) 에 전달 해 야 합 니 다. 먼저 R [o] * = 10 ^ len [fa], 그리고 R [o] + = ragR [fa] * n, 그리고 tagR [o]= tagR [o] * 10 ^ len [fa], ok, 오른쪽 가 수 는 간단 합 니 다. 이제 tagL [o] 와 L [o] 로 왼쪽 가 수 를 해결 합 니 다. tagL [o] 가 표시 하 는 숫자 는 tagR [o] 순서 가 반대 입 니 다. L [o] 는 이 구간 의 모든 숫자 왼쪽 의 절반 에 10 ^ len / 2 의 총 화 를 곱 하고 sum [o] 를 구간 '총화' 로 설정 합 니 다. 초기 값 sum [o] 을 구간 길이 로 한 번 씩 구간 을 업데이트 하면 이 구간 의 sum [o]* = 100, 하 전 태그: L [o] = L [o] * 10 ^ len [fa] (오른쪽 에 이렇게 많이 추가 되 었 기 때문에) + tagL [fa] * sum [o] * 10 ^ len [fa], tagL [o] = tagL [o] + tagL [fa] * 10 ^ len [o]) 을 마지막 으로 len [o] + = len [fa], sum [o] * = 10 ^ (len [fa] * 2) 을 업데이트 합 니 다.
#include
#define ll long long
using namespace std;
const int maxn = 2e5 + 10, mod = 1e9 + 7;
ll sum[maxn * 4], L[maxn * 4], R[maxn * 4], tagL[maxn * 4], tagR[maxn * 4], p[maxn];
int len[maxn * 4];
char s[20];
#define ls o * 2
#define rs o * 2 + 1
void gao(int o, int fa, int n) {
R[o] = (R[o] * p[len[fa]] + tagR[fa] * n) % mod;
tagR[o] = (tagR[o] * p[len[fa]] + tagR[fa]) % mod;
len[o] += len[fa];
L[o] = (L[o] * p[len[fa]] % mod + tagL[fa] * sum[o] % mod * p[len[fa]] % mod) % mod;
tagL[o] = (tagL[o] + tagL[fa] * p[len[o] - len[fa]]) % mod;
sum[o] = sum[o] * p[len[fa] * 2] % mod;
}
void pushdown(int o, int l, int m, int r) {
if (len[o]) {
gao(ls, o, m - l + 1);
gao(rs, o, r - m);
tagL[o] = tagR[o] = len[o] = 0;
}
}
void pushup(int o) {
L[o] = (L[ls] + L[rs]) % mod;
R[o] = (R[ls] + R[rs]) % mod;
sum[o] = (sum[ls] + sum[rs]) % mod;
}
void build(int o, int l, int r) {
L[o] = R[o] = tagL[o] = tagR[o] = len[o] = 0;
if (l == r) {
sum[o] = 1;
return;
}
int m = (l + r) / 2;
build(ls, l, m);
build(rs, m + 1, r);
pushup(o);
}
void up(int o, int l, int r, int ql, int qr, int x) {
if (l >= ql && r <= qr) {
tagR[o] = (tagR[o] * 10 + x) % mod;
len[o]++;
R[o] = (R[o] * 10 + 1ll * x * (r - l + 1)) % mod;
L[o] = (L[o] * 10 + sum[o] * x * 10) % mod;
tagL[o] = (tagL[o] + p[len[o] - 1] * x) % mod;
sum[o] = sum[o] * 100 % mod;
return;
}
int m = (l + r) / 2;
pushdown(o, l, m, r);
if (ql <= m)
up(ls, l, m, ql, qr, x);
if (qr > m)
up(rs, m + 1, r, ql, qr, x);
pushup(o);
}
ll qu(int o, int l, int r, int ql, int qr) {
if (l >= ql && r <= qr)
return (L[o] + R[o]) % mod;
int m = (l + r) / 2;
pushdown(o, l, m, r);
ll res = 0;
if (ql <= m)
res += qu(ls, l, m, ql, qr);
if (qr > m)
res += qu(rs, m + 1, r, ql, qr);
return res % mod;
}
int main() {
int T, kase = 0;
scanf("%d", &T);
p[0] = 1;
for (int i = 1; i <= 200000; i++)
p[i] = p[i - 1] * 10 % mod;
while (T--) {
int n, m, l, r, x;
printf("Case %d:
", ++kase);
scanf("%d%d", &n, &m);
build(1, 1, n);
while (m--) {
scanf("%s%d%d", s, &l, &r);
if (s[0] == 'w') {
scanf("%d", &x);
up(1, 1, n, l, r, x);
}
else
printf("%lld
", qu(1, 1, n, l, r));
}
}
}
1009. Strength
제목: 당신 은 m 개의 카드 를 가지 고 있 거나 공격 상태 에 있 거나 방어 상태 에 있 습 니 다. 나 는 n 개의 카드 를 가지 고 있 습 니 다. 카드 마다 한 번 만 사용 할 수 있 습 니 다. 나 는 카드 한 장 을 선택 하여 당신 의 공격 상태 카드 를 공격 하면 나의 카드 공 격 력 > = 당신 의 카드 공 격 력 이 있 으 면 당신 의 그 공격 당 한 카드 는 폐기 되 고 공 격 력 이 떨 어 지 는 혈 량 을 손실 할 것 입 니 다.만약 내 가 당신 의 방어 상 태 를 공격 하 는 카드 를 선택한다 면, 나의 카드 공 격 력 > = 당신 의 카드 공 격 력 이 있다 면, 당신 의 카드 는 폐기 되 지만, 당신 은 피 를 손실 하지 않 을 것 입 니 다. 만약 당신 이 카드 가 남지 않 았 다 면, 당신 이 손실 한 피 는 나의 남 은 카드 의 공 격 력 총화 가 될 것 입 니 다.가장 큰 피 해 를 주 십시오.
해법: 우 리 는 두 가지 전략 만 있 으 면 됩 니 다. 첫 번 째: 나의 모든 카드 는 당신 의 공격 상태 카드 를 공격 합 니 다. 두 번 째: 나 는 먼저 당신 의 방어 상태 카드 를 모두 공격 합 니 다. 만약 에 내 가 카드 가 남 으 면 모두 당신 의 공격 상태 카드 를 공격 합 니 다. 만약 에 남 으 면 모두 당신 을 공격 합 니 다.방어 상 태 를 공격 하 는 카드 의 욕심 전략 은 너무 간단 하 다. 우 리 는 공격 상태의 카드 를 어떻게 공격 하 는 지 에 대해 이야기 하 자. 우리 문 은 먼저 2 점 이나 더 블 포인터 로 내 가 상대방 의 카드 몇 개 를 이 길 수 있 는 지 를 구 한 다음 에 나 는 상대방 의 카드 와 정렬 을 한다. 만약 에 내 가 k 개의 카드 를 가장 많이 이 길 수 있다 고 가정 하면 우리 문 은 1 부터 매 거 i.나의 가장 큰 i 장의 카드 와 - 상대방 의 가장 작은 i 장의 카드 의 합 은 바로 상대방 이 단 추 를 한 혈 량 입 니 다. 우리 가 최대 치 를 취하 면 됩 니 다.
#include
#define ll long long
using namespace std;
const int maxn = 1e5 + 10;
int a[maxn], b[maxn], c[maxn], d[maxn], vis[maxn], n1, n2, n3;
ll sum1[maxn], sum2[maxn];
int ok(int k) {
int p = n1 - k;
for (int i = 1; i <= k; i++)
if (a[i + p] < b[i])
return 0;
return 1;
}
ll gao(int tp) {
if (!n2) {
if (!tp)
return 0;
return sum1[n1];
}
if (a[n1] <= b[1])
return 0;
int l = 1, r = min(n1, n2);
while (l < r) {
int m = (l + r) / 2;
if (ok(m))
l = m + 1;
else
r = m;
}
if (!ok(l))
l--;
ll ans = 0;
if (tp && l == n2)
ans = sum1[n1] - sum2[n2];
for (int i = 1; i <= l; i++)
ans = max(ans, sum1[n1] - sum1[n1 - i] - sum2[i]);
return ans;
}
int gao2() {
if (!n3 || n1 == n3)
return 1;
int p = 1, q = 1;
while (p <= n1 && q <= n3)
if (a[p] >= c[q]) {
vis[p] = 1;
p++, q++;
}
else
p++;
if (q <= n3)
return 0;
int tmp = n1;
n1 = 0;
for (int i = 1; i <= tmp; i++)
if (!vis[i])
a[++n1] = a[i], sum1[n1] = sum1[n1 - 1] + a[n1];
return 1;
}
int main() {
int T, kase = 0;
scanf("%d", &T);
while (T--) {
int n, m, x;
scanf("%d%d", &n, &m);
n1 = n2 = n3 = 0;
for (int i = 1; i <= n; i++)
scanf("%d", &a[++n1]), vis[i] = 0;
for (int i = 1; i <= m; i++)
scanf("%d", &d[i]);
for (int i = 1; i <= m; i++) {
scanf("%d", &x);
if (x)
c[++n3] = d[i];
else
b[++n2] = d[i];
}
sort(a + 1, a + 1 + n1);
sort(b + 1, b + 1 + n2);
sort(c + 1, c + 1 + n3);
for (int i = 1; i <= n1; i++)
sum1[i] = sum1[i - 1] + a[i];
for (int i = 1; i <= n2; i++)
sum2[i] = sum2[i - 1] + b[i];
ll ans = gao(0);
if (gao2())
ans = max(ans, gao(1));
printf("Case %d: %lld
", ++kase, ans);
}
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
[낙 곡] P2880 [USACO07JAN] 밸 런 스 라인업 Balanced Lineup (\# 트 리 배열)제목 배경 제목 설명: 어느 날, 존 은 일부 소 들 에 게 플 라 잉 경 기 를 시 키 기로 결정 했다. 그 는 대열 에 연 속 된 소 를 찾 아 경 기 를 하려 고 한다. 그러나 수준 차 이 를 피하 기 위해 소...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.