2019-08-23 KEI NOIP Simulation Group A

T1 [JZOJ2908] matrix multiplication

Title Description

  Give you an N * N matrix, matrix multiplication do not count, but each time asked a K-decimal sub rectangle.

data range

  For $ 20 \% $ data, $ N \ leq 100 $, $ Q \ leq 10 ^ 3 $

  For $ 40 \% $ data, $ N \ leq 300 $, $ Q \ leq 10 ^ 4 $

  For $ 60 \% $ data, $ N \ leq 400 $, $ Q \ leq 3 \ times 10 ^ 4 $

  For $ 100 \% $ data, $ N \ leq 500 $, $ Q \ leq 6 \ times 10 ^ 4 $

analysis

  As a data structure dish of chicken how to do such a topic

  // + overall two-dimensional array of binary tree

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
#define inf 0x3f3f3f3f
#define N 502
#define M 60005

inline int read() {
    int x = 0, f = 1; char ch = getchar();
    while (!isdigit(ch)) {if (ch == '-') f = -1; ch = getchar();}
    while ( isdigit(ch)) {x = x * 10 + ch - '0'; ch = getchar();}
    return x *= f;
}

int n, m, t[N][N];
int id[M], cur[M], ans[M], q1[M], q2[M];

struct Mat {int x, y, v;} g[N * N];
bool cmp(Mat a, Mat b) {return a.v < b.v;}
struct Query {int x1, y1, x2, y2, k;} q[M];

inline int lowbit(int x) {return x & -x;}

inline void add(int x, int y, int v) {
    for (int i = x; i <= n; i += lowbit(i))
        for (int j = y; j <= n; j += lowbit(j))
            t[i][j] += v;
}

inline int pre(int x, int y) {
    int sum = 0;
    for (int i = x; i; i -= lowbit(i))
        for (int j = y; j; j -= lowbit(j))
            sum += t[i][j];
    return sum;
}

inline int sub(int x1, int y1, int x2, int y2) {
    int sum = pre(x2, y2);
    sum -= pre(x1 - 1, y2) + pre(x2, y1 - 1);
    sum += pre(x1 - 1, y1 - 1);
    return sum;
}

void solve(int l, int r, int ql, int qr) {
    if (ql > qr) return;
    if (l == r) {
        for (int i = ql; i <= qr; i++) ans[id[i]] = g[l].v;
        return;
    }
    int mid = (l + r) >> 1, cnt1 = 0, cnt2 = 0;
    for (int i = l; i <= mid; i++) add(g[i].x, g[i].y, 1);
    for (int i = ql, j = id[i]; i <= qr; j = id[++i]) {
        int sum = cur[j] + sub(q[j].x1, q[j].y1, q[j].x2, q[j].y2);
        if (sum >= q[j].k) q1[++cnt1] = j;
        else q2[++cnt2] = j, cur[j] = sum;
    }
    int cnt = ql - 1;
    for (int i = 1; i <= cnt1; i++) id[++cnt] = q1[i];
    for (int i = 1; i <= cnt2; i++) id[++cnt] = q2[i];
    for (int i = l; i <= mid; i++) add(g[i].x, g[i].y, -1);
    solve(l, mid, ql, ql + cnt1 - 1);
    solve(mid + 1, r, ql + cnt1, qr);
}

int main(){
    n = read(); m = read();
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++) {
            g[(i - 1) * n + j].x = i;
            g[(i - 1) * n + j].y = j;
            g[(i - 1) * n + j].v = read();
        }
    sort(g + 1, g + n * n + 1, cmp);
    for (int i = 1; i <= m; i++) {
        q[i].x1 = read(); q[i].y1 = read();
        q[i].x2 = read(); q[i].y2 = read();
        q[i].k = read(); id[i] = i;
    }
    solve(1, n * n, 1, m);
    for (int i = 1; i <= m; i++)
        printf("%d\n", ans[i]);
    
    return 0;
}
View Code

T2 [JZOJ3410] Tree

Title Description

  Wayne playing in a very fun game. In the game, Wayne built the N cities, and now he wants to repair some of the roads in between these cities, of course, not between any two cities can repair, for aesthetic road system, a total of only M inter-city can repair roads, i.e., a number of triplets (Ui, Vi, Ci) has between Ui and Vi represents a Ci bidirectional path length. Of course, the game ensures that, if all roads are built, then any two cities can reach each other.

  Wayne has exactly N - 1 Zhi build teams, and each team can only repair a road. Of course, the greater the length of the construction, the construction of higher exertion, highway construction game set will have a length of C of C exertion. When all the teams completed the entire city group should be connected, and the construction team who will look at these tired of other teams, if the difference is too great exertion circumstances, might lead to unrest, is not conducive to social harmony. Wayne on this issue is a headache, so he wanted to know, that N - 1 standard deviation Zhi team exertion can have a minimum number.

data range

  For $ 20 \% $ data, $ M \ leq 20 $

  Further data for $ 30 \% of $, $ C \ leq 10 $

  For $ 100 \% $ data, $ N \ leq 100 $, $ M \ leq 2000 $, $ C \ leq 100 $

analysis

  Wrote a law on the examination of water, was found positive solution seems to be loved

  First, this is a minimum spanning tree standard deviation

  Just beginning to discover $ C $ is very small, and this feeling about the solution, I think of the average number of enumeration

  However, the average direct enumeration does not exist, taking into account the standard deviation is a quantity of data representing the stability, can be enumerated length value within reasonable limits, choose the closest road to make the length of the tree and then calculates the real averaging the standard deviation to update the answer

  Since the length of all the roads are positive integers, so for $ x \ in (0.5k, 0.5k + 0.5) \; (k \ in N) $, when $ k $ takes a fixed value, regardless of what get $ X $ value, the result of all roads according to the length of the difference $ X $ in ascending order are the same

  It is only necessary every $ 0.25 $ enumerate a length value, of course, can be the length of all roads are multiplied by $ 4 $

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 105
#define M 2005 

inline int read() {
    int x = 0, f = 1; char ch = getchar();
    while (ch < '0' || ch > '9') {if (ch == '-') f = -1; ch = getchar();}
    while (ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
    return x *= f;
}

double ans = 1000000000.0;
int n, m, maxe, mine = inf;
int f[N], q[N];

struct Edge {int u, v, w, d;} e[M];
bool cmp(Edge a, Edge b) {return a.d < b.d;}

int find(int x) {
    if (x == f[x]) return x;
    return f[x] = find(f[x]);
}

int main() {
    n = read(); m = read();
    for (int i = 1; i <= m; i++) {
        e[i].u = read(); e[i].v = read(); e[i].w = read() * 4;
        maxe = max(maxe, e[i].w); mine = min(mine, e[i].w);
    }
    for (int k = mine; k <= maxe; k++) {
        for (int i = 1; i <= m; i++) e[i].d = abs(e[i].w - k);
        sort(e + 1, e + m + 1, cmp);
        int cnt = 0, sum = 0; double now = 0;
        for (int i = 1; i <= n; i++) f[i] = i;
        for (int i = 1; i <= m; i++) {
            int x = find(e[i].u), y = find(e[i].v);
            if (x == y) continue; f[x] = y;
            q[++cnt] = i; sum += e[i].w / 4;
            if (cnt == n - 1) break;
        }
        double avg = (double)sum / (double)(n - 1);
        for (int i = 1; i < n; i++)
            now += (e[q[i]].w / 4.0 - avg) * (e[q[i]].w / 4.0 - avg);
        now = sqrt(now / (n - 1));
        ans = min(ans, now);
    }
    printf("%.4lf", ans);
    
    return 0;
}
View Code

T3 [JZOJ3682] Points and Segments

Title Description

  Lahub inadequately prepared on geometry problems, but he heard that this year's IOI selection camp will be many geometric problems. Deep fear Lahub he locked himself in the basement, and start thinking about new topics in this category. Wherein one of the following.
Videos Lahub want axis OX of n different segments [li, ri]. Segments which can be either red and blue. Drawings can be "good" if and only if the following conditions are satisfied:

  For each point x axis OX, considering all segments comprise point x, rx is provided with a blue-red line segment and a line segment including the point bx x, must satisfy the inequality | rx-bx | <= 1.

  Segment [l, r] contains the point x if and only if l <= x <= r.

  Lahub to all of you about the endpoint of the line, you have to find a "good" painting to him.

data range

  For $ 20 \% $ data, $ N \ leq 10 $

  For $ 40 \% $ data, $ N \ leq 10 ^ 3 $

  For $ 100 \% $ data, $ N \ leq 10 ^ 5 $

analysis

  According to the idea of ​​the difference, sections were stained section, plus the equivalent of $ $ L, $ r + 1 $ Save

  First, of course we take discrete points, and for each interval we can connect an undirected edges between L $ $ $ r + 1 $ and

  如果图中存在奇点(一定为偶数个),则可以从小到大组成若干对点,在每对点之间连一条虚边(任意两条虚边之间不存在重合部分),此时就形成了一个欧拉回路

  于是可以在图上跑一边欧拉回路,若经过某条边时方向向左,则对应区间被染成红色,反之则被染成蓝色,这样就能保证在每个点上红色和蓝色的覆盖次数之差的绝对值不超过 $1$

  因为这是个欧拉回路,覆盖每个点的红色区间和蓝色区间数量一定相等,且每个点最多被一条虚边覆盖,所以删去虚边后仍然符合题意

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
using namespace std;
#define inf 0x3f3f3f3f
#define N 200005

inline int read() {
    int x = 0, f = 1; char ch = getchar();
    while (ch < '0' || ch > '9') {if (ch == '-') f = -1; ch = getchar();}
    while (ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
    return x *= f;
}

int n, m, tot = 1, last;
int to[N << 1], num[N << 1], nxt[N << 1], head[N];
int q[N], d[N], vis[N], used[N << 1], ans[N >> 1];
struct Data {int l, r;} t[N >> 1];

void add(int u, int v, int w) {
    to[++tot] = v; num[tot] = w;
    nxt[tot] = head[u]; head[u] = tot;
}

void dfs(int x) {
    vis[x] = 1;
    for (int &i = head[x]; i; i = nxt[i])
        if (!used[i]) {
            used[i] = used[i ^ 1] = 1;
            ans[num[i]] = (to[i] > x);
            dfs(to[i]);
        }
}

int main(){
    n = read();
    for (int i = 1; i <= n; i++) {
        t[i].l = read(); t[i].r = read() + 1;
        q[++m] = t[i].l; q[++m] = t[i].r;
    }
    sort(q + 1, q + m + 1);
    m = unique(q + 1, q + m + 1) - q - 1;
    for (int i = 1; i <= n; i++) {
        t[i].l = lower_bound(q + 1, q + m + 1, t[i].l) - q;
        t[i].r = lower_bound(q + 1, q + m + 1, t[i].r) - q;
        add(t[i].l, t[i].r, i); add(t[i].r, t[i].l, i);
        d[t[i].l]++; d[t[i].r]++;
    }
    for (int i = 1; i <= m; i++)
        if (d[i] & 1) {
            if (last) {
                add(last, i, 0); add(i, last, 0);
                d[last]++; d[i]++; last = 0;
            }
            else last = i;
        }
    for (int i = 1; i <= m; i++) if (!vis[i]) dfs(i);
    for (int i = 1; i <= n; i++) printf("%d ", ans[i]);
    
    return 0;
}
View Code

Guess you like

Origin www.cnblogs.com/Pedesis/p/11402597.html