牛客多校4

J

题意:给你一个hash表,让你给出一个字典序最小的输入。

思路:按数字大小从小到大插入,用链表和bit维护过程。

#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define pii pair<int, int>
#define y1 skldjfskldjg
#define y2 skldfjsklejg

using namespace std;

const int N = 2e5 + 7;
const int M = 1e5 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 +7;

int n, tot, all, ans[N], a[N], L[N], R[N];
vector<pii> vec;
struct node {
    int nx, pre, val;
} b[N];

struct BIT {
    int a[N];
    void init(int n) {
        for(int i = 0; i <= n; i++) a[i] = 0;
    }
    void modify(int x, int v) {
        for(int i = x; i <= n; i += i & -i)
            a[i] += v;
    }

    int sum(int x) {
        int ans = 0;
        for(int i = x; i; i -= i & -i)
            ans += a[i];
        return ans;
    }
} bit;

void del(int u) {
    int to = b[u].nx;
    int from = b[u].pre;
    b[from].nx = b[u].nx;
    b[to].pre = b[u].pre;
}

bool is(int l, int r) {
    if(l == r) return true;
    if(l < r) return bit.sum(r) - bit.sum(l - 1) == (r - l);
    return bit.sum(r) + bit.sum(n) - bit.sum(l - 1) == (r + n - l);
}

void check(int u, int fa) {
    if(u == fa || b[u].val == -1 || !is(L[u], R[u])) return;
    int to = b[u].nx;
    ans[tot++] = b[u].val;
    bit.modify(u, 1);
    del(u);
    check(to, u);

}
int main() {

    int T; scanf("%d", &T);
    while(T--) {
        tot = 0; all = 0;
        vec.clear();
        scanf("%d", &n);
        bit.init(n);
        for(int i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
            b[i].val = -1;
            b[i].nx = (i + 1 - 1) % n + 1;
            b[i].pre = (i - 1 - 1 + n) % n + 1;
            if(a[i] != -1) {
                L[i] = a[i] % n + 1;
                R[i] = i;
                vec.push_back(mk(a[i], i));
            }

        }
        sort(vec.begin(), vec.end());

        for(int i = 0; i < vec.size(); i++) {
            int l = vec[i].fi % n + 1, r = vec[i].se;
            b[r].val = vec[i].fi;
            if(is(l, r)) {
                check(r, -1);
            }
        }

        if(tot != vec.size()) {
            puts("-1");
        } else {
            if(tot == 0) {
                puts("");
            } else {
                printf("%d", ans[0]);
                for(int i = 1; i < tot; i++) printf(" %d", ans[i]);
                puts("");
            }
        }
    }
    return 0;
}


/*
1
10
8 10 -1 -1 34 75 86 55 88 18
*/
View Code

 

线段树优化建边写法

#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define pii pair<int,int>
#define pLL pair<long long, long long>
#define piii pair<int, pair<int,int>>

using namespace std;

const int N = 2e5 + 7;
const int M = 1e4 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-10;
const double PI = acos(-1);

int ans[N], a[N], id[N << 2], idx, sum, tot, n;
vector<int> edge[N << 2];
bool f[N << 2];
struct node {
    int val, deg, id;
    bool operator < (const node &rhs) const {
        return val > rhs.val;
    }
} p[N << 2];

void build(int l, int r, int rt) {
    if(l == r) {
        id[rt] = l;
        edge[id[rt]].clear();
        p[id[rt]].deg = 0;
        p[id[rt]].val = a[l];
        p[id[rt]].id = l;
        if(a[l] < 0) f[rt] = true;
        else f[rt] = false;
        return;
    }
    id[rt] = idx++;
    edge[id[rt]].clear();
    p[id[rt]].deg = 0;
    p[id[rt]].val = -2;
    p[id[rt]].id = id[rt];
    int mid = l + r >> 1;
    build(l, mid, rt << 1);
    build(mid + 1, r, rt << 1 | 1);
    edge[id[rt << 1]].push_back(id[rt]);
    edge[id[rt << 1 | 1]].push_back(id[rt]);
    p[id[rt]].deg += 2;
    f[rt] = f[rt << 1] | f[rt << 1 | 1];
}

bool addEdge(int L, int R, int to, int l, int r, int rt) {
    if(l >= L && r <= R) {
        edge[id[rt]].push_back(to);
        p[to].deg++;
        return f[rt];
    }
    int mid = l + r >> 1;
    bool ans = false;
    if(L <= mid) ans |= addEdge(L, R, to, l, mid, rt << 1);
    if(R > mid) ans |= addEdge(L, R, to, mid + 1, r, rt << 1 | 1);
    return ans;
}

int main() {
    int T; scanf("%d", &T);
    while(T--) {
        scanf("%d", &n); idx = n; sum = 0;
        for(int i = 0; i < n; i++) {
            scanf("%d", &a[i]);
            if(a[i] != -1) sum++;
        }

        build(0, n - 1, 1);

        bool judge = false;
        for(int i = 0; i < n; i++) {
            if(a[i] == -1) continue;
            int l = a[i] % n, r = i;
            if(l < r) {
                judge |= addEdge(l, r - 1, i, 0, n - 1, 1);
            } else if(l > r) {
                if(r) judge |= addEdge(0, r - 1, i, 0, n - 1, 1);
                judge |= addEdge(l, n - 1, i, 0, n - 1, 1);
            }
            if(judge) break;
        }

        if(judge) {
            puts("-1");
        } else {
            priority_queue<node> que; tot = 0;
            for(int i = 0; i < idx; i++)
                if(p[i].deg == 0) que.push(p[i]);

            while(!que.empty()) {
                node u = que.top(); que.pop();
                if(u.val >= 0) ans[tot++] = u.val;
                for(int i = 0; i < edge[u.id].size(); i++) {
                    int v = edge[u.id][i];
                    p[v].deg--;
                    if(!p[v].deg) que.push(p[v]);
                }
            }

            if(tot < sum) {
                puts("-1");
            } else {
                if(!tot) puts("");
                else {
                    printf("%d", ans[0]);
                    for(int i = 1; i < tot; i++) printf(" %d", ans[i]);
                    puts("");
                }
            }
        }
    }
    return 0;
}

/*
*/
View Code

 

E

题意:这个题意真的是看不懂。。  给你n个点,每个点都有一个出现概率,一个点会覆盖自己左下角的区域,

问你期望的面积是多少。

 

思路:很容易想到扫描线维护面积并,用线段树维护一下在未被覆盖的概率。

#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define pii pair<int, int>
#define y1 skldjfskldjg
#define y2 skldfjsklejg

using namespace std;

const int N = 1e5 + 7;
const int M = 1e5 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 +7;

int n, hs[N], pos[N], tot;
LL x[N], y[N], z[N], f[N], a[N << 2], lazy[N << 2];

LL fastPow(LL a, LL b) {
    LL ans = 1;
    while(b) {
        if(b & 1) ans = ans * a % mod;
        a = a * a % mod; b >>= 1;
    }
    return ans;
}

void build(int l, int r, int rt) {
    lazy[rt] = 1;
    if(l == r) {
        a[rt] = hs[l + 1] - hs[l];
        return;
    }
    int mid = l + r >> 1;
    build(l, mid, rt << 1);
    build(mid + 1, r, rt << 1 | 1);
    a[rt] = (a[rt << 1] + a[rt << 1 | 1]) % mod;
}

void pushdown(int rt) {
    if(lazy[rt] == 1) return;
    lazy[rt << 1] = lazy[rt << 1] * lazy[rt] % mod;
    lazy[rt << 1 | 1] = lazy[rt << 1 | 1] * lazy[rt] % mod;
    a[rt << 1] = a[rt << 1] * lazy[rt] % mod;
    a[rt << 1 | 1] = a[rt << 1 | 1] * lazy[rt] % mod;
    lazy[rt] = 1;
}

void update(int L, int R, LL v, int l, int r, int rt) {
    if(l >= L && r <= R) {
        lazy[rt] = lazy[rt] * v % mod;
        a[rt] = a[rt] * v % mod;
        return;
    }
    int mid = l + r >> 1;
    pushdown(rt);
    if(L <= mid) update(L, R, v, l, mid, rt << 1);
    if(R > mid) update(L, R, v, mid + 1, r, rt << 1 | 1);
    a[rt] = (a[rt << 1] + a[rt << 1 | 1]) % mod;
}

LL query(int L, int R, int l, int r, int rt) {
    if(l >= L && r <= R) return a[rt];
    int mid = l + r >> 1; LL ans = 0;
    pushdown(rt);
    if(L <= mid) ans = query(L, R, l, mid, rt << 1);
    if(R > mid) ans = (ans + query(L, R, mid + 1, r, rt << 1 | 1)) % mod;
    return ans;
}

struct node {
    bool operator < (const node &rhs) const {
        return x < rhs.x;
    }
    int x, y;
    LL p;
} qus[N];

int main() {
    int T; scanf("%d", &T);
    while(T--) {
        tot = 0;
        scanf("%d", &n);
        for(int i = 1; i <= n; i++) {
            scanf("%d%d", &qus[i].x, &qus[i].y);
            scanf("%lld%lld", &x[i], &y[i]);
            f[i] = x[i] * fastPow(y[i], mod - 2) % mod;
            z[i] = (1 - f[i] + mod) % mod;
            hs[++tot] = qus[i].y;
        }
        hs[++tot] = 0;
        sort(hs + 1, hs + tot + 1);
        tot = unique(hs + 1, hs + tot + 1) - hs - 1;
        hs[tot + 1] = hs[tot];
        build(1, tot, 1);

        for(int i = 1; i <= n; i++) {
            qus[i].y = lower_bound(hs + 1, hs + tot + 1, qus[i].y) - hs;
            update(1, qus[i].y - 1, z[i], 1, tot, 1);
            qus[i].p = fastPow(z[i], mod - 2);
        }

        sort(qus + 1, qus + 1 + n);
        LL ans = 0; qus[0].x = 0;

        for(int i = 1; i <= n; i++) {
            LL lenx = qus[i].x - qus[i - 1].x;
            LL leny = (hs[tot] - a[1] + mod) % mod;
            ans += lenx * leny % mod;
            if(ans >= mod) ans -= mod;
            update(1, qus[i].y - 1, qus[i].p, 1, tot, 1);
        }

        printf("%lld\n", ans);
    }
    return 0;
}


/*
*/
View Code

 

C

数位dp

#include<bits/stdc++.h>
#define LL long long
#define ll long long
#define fi first
#define se second
#define mk make_pair
#define pii pair<int, int>
#define y1 skldjfskldjg
#define y2 skldfjsklejg

using namespace std;

const int N = 1e5 + 7;
const int M = 1e5 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const LL mod = 1e9 + 7;
const int maxn = 1e5;

int f[64][128][2], tot;
LL n;
int s[64];

void add(int &a, int b) {
    a += b; if(a >= mod) a -= mod;
}

int dp(int pos, int p, bool fg, int cnt) {
    if(pos == -1) return p == -1 ? 0 : abs(cnt - 64);
    if(p != -1 && !fg && f[pos][cnt][p] != -1) return f[pos][cnt][p];
    int up = fg ? s[pos] : 1;
    int ret = 0;
    for(int i = 0; i <= up; i++) {
        if(p == -1) {
            if(!i) add(ret, dp(pos - 1, p, fg && i == up, cnt));
            else add(ret, dp(pos - 1, 1, fg && i == up, cnt));
        } else {
            add(ret, dp(pos - 1, i, fg && i == up, cnt + ((i == p) ? -1 : 1)));
        }
    }
    if(p != -1 && !fg) f[pos][cnt][p] = ret;
    return ret;
}

int main() {
    int T; scanf("%d", &T);
    memset(f, -1, sizeof(f));
    while(T--) {
        scanf("%lld", &n); tot = 0;
        while(n) {
            if(n & 1) s[tot++] = 1;
            else s[tot++] = 0;
            n >>= 1;
        }
        printf("%d\n", dp(tot - 1, -1, 1, 64));
    }
    return 0;
}

/*\
10
10
*/
View Code

 

posted @ 2018-07-29 17:02  NotNight  阅读(180)  评论(0编辑  收藏  举报