2018년 3월 23일 금요일

10323 Excellent Engineers

10323 Excellent Engineers https://www.acmicpc.net/problem/10323
2336 굉장한 학생 https://www.acmicpc.net/problem/2336

각 사람마다 communication skills, programming skills, algorithmic knowledge가 등수로 주어진다.
어떤 사람의 세 가지 등수보다 모두 높은 등수를 가진 사람이 존재하면 그사람을 추천해서는 안된다.
사람들의 등수가 주어질 때 추천할 수 있는 사람의 수를 구하는 문제이다.

세 등 수중 앞의 등수를 기준으로 정렬하면 차원 하나를 줄일 수 있다.
그 후에 segment tree로 관리를 해주면서 값을 갱신해나가면 된다.
#include <bits/stdc++.h>
using namespace std;
#define INF 987654321
const int MAXN = 1e5 + 5;
struct Save { int a, b, c; };
int t, n;
Save save[MAXN];
struct Segment {
    int sze;
    vector<int> tree;
    Segment() {}
    Segment(int s) :sze(s) { tree.resize(4 * s, INF); }
    int update(int idx, int val, int node, int nl, int nr) {
        if (nr < idx || nl > idx) return tree[node];
        if (nl == nr) return tree[node] = val;
        int mid = (nl + nr) >> 1;
        return tree[node] = min(update(idx, val, node * 2, nl, mid), update(idx, val, node * 2 + 1, mid + 1, nr));
    }
    void update(int idx, int val) {
        update(idx, val, 10, sze - 1);
    }
    int query(int l, int r, int node, int nl, int nr) {
        if (r < nl || l > nr) return INF;
        if (l <= nl && nr <= r) return tree[node];
        int mid = (nl + nr) >> 1;
        return min(query(l, r, node * 2, nl, mid), query(l, r, node * 2 + 1, mid + 1, nr));
    }
    int query(int l, int r) {
        return query(l, r, 10, sze - 1);
    }
};
int main() {
    scanf("%d",&t);
    while (t--) {
        scanf("%d"&n);
        for (int i = 0; i < n; i++scanf("%d%d%d"&save[i].a, &save[i].b, &save[i].c);
        sort(save, save + n, [](Save &a, Save &b)->bool {
            return a.a < b.a;
        });
        Segment seg(n + 1);
        int ans = n;
        for (int i = 0; i < n; i++) {
            int mn = seg.query(0, save[i].b - 1);
            if (mn < save[i].c) ans--;
            seg.update(save[i].b, save[i].c);
        }
        printf("%d\n", ans);
    }
    return 0;
}
cs

2018년 3월 4일 일요일

11046 팰린드롬??

11046 팰린드롬?? https://www.acmicpc.net/problem/11046

자연수 N개가 주어진다.
M개의 쿼리마다 $s$부터$e$구간 까지 팰린드롬을 이루는지 여부를 판단하는 문제이다.

Manacher's algorithm으로 전처리하여 각 쿼리마다 $O(1)$에 처리할 수 있다.
짝수의 팰린드롬도 처리하기 위해 시작,끝,중간마다 $-1$을 집어넣었다.

const int MAXN = 1e6 + 6;
int arr[MAXN * 2 + 6];
cs
이 문제를 20번 넘게 정도 제출했는데 위와 같이 const 변수에 곱셈을 적용시키면 안된다ㅠㅠ

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 2e6 + 6;
int N, M;
int arr[MAXN];
int A[MAXN];
int main() {
    scanf("%d"&N);
    arr[0= -1;
    for (int n = 0; n < N; n++) {
        scanf("%d"&arr[2*+ 1]);
        arr[2 * n + 2= -1;
    }
    N = 2 * N + 1;
 
    int r = 0, p = 0;
    for (int n = 0; n < N; n++) {
        if (n <= r) A[n] = min(A[2 * p - n], r - n);
        while (n - A[n] - 1 >= 0 && n + A[n] + 1 < N && arr[n - A[n] - 1== arr[n + A[n] + 1]) A[n]++;
        if (r < n + A[n]) r = n + A[n], p = n;
    }
 
    scanf("%d"&M);
    for (int m = 0; m < M; m++) {
        int s, e;
        scanf("%d%d"&s, &e);
        int len = e - s + 1;
        s--; s *= 2; s++;
        e--; e *= 2; e++;
        int mid = (s + e) >> 1;
        printf("%d\n", A[mid] >= len ? 1 : 0);
    }
    return 0;
}
cs