牛客练习赛26

C 城市规划

ps:想复杂了,记录每个点靠的最近的左端点和枚举到这个点时,上次切割的位置。(每次切割都切右端点

namespace fastIO {
    #define BUF_SIZE 100000
    bool IOerror = 0;
    inline char nc() {
        static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE;
        if(p1 == pend) {
            p1 = buf;
            pend = buf + fread(buf, 1, BUF_SIZE, stdin);
            if(pend == p1) {
                IOerror = 1;
                return -1;
            }
        }
        return *p1++;
    }
    inline bool blank(char ch) {
        return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t';
    }
    inline void read(int &x) {
        char ch;
        while(blank(ch = nc()));
        if(IOerror) return;
        for(x = ch - '0'; (ch = nc()) >= '0' && ch <= '9'; x = x * 10 + ch - '0');
    }
    #undef BUF_SIZE
};
using namespace fastIO;

const int N = 1000005;

int n, m;
int a[N];

int main()
{
    read(n);
    read(m);
    int l, r;
    Rep(i, 1, m) {
        read(l);
        read(r);
        if (a[r] < l) a[r] = l;
    }

    int ans = 0, cut = a[1];
    Rep(i, 1, n) if (a[i]) {
        if (a[i] >= cut) {
            ans++;
            cut = i;
        }
    }
    pr(ans);
    return 0;
}

D XOR序列

 ps:x ^ ? = y,则 ? = x ^ y。所以问题转化为:这n个数的线性基能否表示出 ?。

int n, q;
LL p[100];

void Insert(int x) {
    for (int i = 62; ~i; --i) if ((1 << i) & x) {
        if (!p[i]) {
            p[i] = x;
            break;
        }
        x ^= p[i];
    }
}

bool check(int x) {
    for (int i = 62; ~i; --i) if ((x & (1 << i)) && p[i]) {
        x ^= p[i];
    }
    return (x == 0);
}

int main()
{
    sc(n);
    Rep(i, 1, n) {
        int x;
        sc(x);
        Insert(x);
    }
    sc(q);
    while(q--) {
        int x, y;
        sc(x), sc(y);
        if (check(x ^ y)) puts("YES");
        else puts("NO");
    }
    return 0;
}

 树上路径

ps:设最短路径上的点的和为a,点的平方和为b,则 ans = (a * a — b) / 2。然后 a^2 和 b 分别用树剖+线段树维护就行了。注意取模 !!!!!!!!

const int N = 100005;
const int mod = 1000000007;
const int inv2 = 500000004;

int n, m;
int v[N], dep[N], pa[N], id[N], rk[N], sz[N], son[N], top[N];


struct BST {
    int cnt;
    int a[N * 4], b[N * 4], use[4 * N];

    void Inite() {
        cnt = 0;
        mem(use, 0);
    }
    void Pushup(int root) {
        a[root] = (0ll + a[lson] + a[rson]) % mod;
        b[root] = (0ll + b[lson] + b[rson]) % mod;
    }
    void Pushdown(int l, int r, int root) {
        use[lson] = (0ll + use[lson] + use[root]) % mod;
        use[rson] = (0ll + use[rson] + use[root]) % mod;
        int mid = (l + r) >> 1;
        b[lson] = (0ll + b[lson] + 1ll * use[root] * use[root] % mod * (mid - l + 1) % mod + 2ll * use[root] * a[lson] % mod) % mod;
        b[rson] = (0ll + b[rson] + 1ll * use[root] * use[root] % mod * (r - mid) % mod + 2ll * use[root] * a[rson] % mod) % mod;
        a[lson] = (0ll + a[lson] + 1ll * (mid - l + 1) * use[root] % mod) % mod;
        a[rson] = (0ll + a[rson] + 1ll * (r - mid) * use[root] % mod) % mod;
        use[root] = 0;
    }
    void Build(int l, int r, int root) {
        if (l == r) {
            a[root] = v[rk[++cnt]];
            b[root] = 1ll * a[root] * a[root] % mod;
            return;
        }
        int mid = (l + r) >> 1;
        Build(l, mid, lson);
        Build(mid + 1, r, rson);
        Pushup(root);
    }
    void Update(int l, int r, int root, int L, int R, int x) {
        if (l > R || r < L) return;
        if (L <= l && r <= R) {
            use[root] = (0ll + use[root] + x) % mod;
            b[root] = (0ll + b[root] + 1ll * x * x % mod * (r - l + 1) % mod + 2ll * x * a[root] % mod) % mod;
            a[root] = (0ll + a[root] + 1ll * x * (r - l + 1) % mod) % mod;
            return;
        }
        int mid = (l + r) >> 1;
        if (use[root]) Pushdown(l, r, root);
        Update(l, mid, lson, L, R, x);
        Update(mid + 1, r, rson, L, R, x);
        Pushup(root);
    }
    int Query(int l, int r, int root, int L, int R, bool flag) {
        if (l > R || r < L) return 0;
        if (L <= l && r <= R) {
            if (flag) return a[root];
            else return b[root];
        }
        if (use[root]) Pushdown(l, r, root);
        int mid = (l + r) >> 1;
        int ans = 0;
        ans = (0ll + ans + Query(l, mid, lson, L, R, flag)) % mod;
        ans = (0ll + ans + Query(mid + 1, r, rson, L, R, flag)) % mod;
        return ans;
    }
};

BST T;

struct TreeCut {
    int cnt;
    vector<int> G[N];

    void Inite() {
        T.Inite();

        cnt = 0;
        mem(son, -1);
        Rep(i, 0, n) G[i].clear();
    }
    void addedge(int u, int v) {
        G[u].pb(v);
        G[v].pb(u);
    }
    void DFS1(int u, int p, int d) {
        pa[u] = p;
        sz[u] = 1;
        dep[u] = d;
        for (auto v : G[u]) if (v != p) {
            DFS1(v, u, d + 1);
            sz[u] += sz[v];
            if (son[u] == -1 || sz[son[u]] < sz[v]) son[u] = v;
        }
    }
    void DFS2(int u, int st) {
        top[u] = st;
        id[u] = ++cnt;
        rk[cnt] = u;
        if (son[u] == -1) return;
        DFS2(son[u], st);
        for (auto v : G[u]) if (v != son[u] && v != pa[u]) DFS2(v, v);
    }

    void Start() {
        DFS1(1, 1, 0);
        DFS2(1, 1);

        T.Inite();
        T.Build(1, n, 1);
    }
    void Update(int u, int v, int x) {
        int pu = top[u], pv = top[v];
        while(pu != pv) {
            if (dep[pu] > dep[pv]) {
                T.Update(1, n, 1, id[pu], id[u], x);
                u = pa[pu];
            }
            else {
                T.Update(1, n, 1, id[pv], id[v], x);
                v = pa[pv];
            }
            pu = top[u], pv = top[v];
        }
        if (id[u] <= id[v]) T.Update(1, n, 1, id[u], id[v], x);
        else T.Update(1, n, 1, id[v], id[u], x);
    }
    int sum(int u, int v) {
        int pu = top[u], pv = top[v];

        int sa = 0, sb = 0;
        while(pu != pv) {
            if (dep[pu] > dep[pv]) {
                sa = (0ll + sa + T.Query(1, n, 1, id[pu], id[u], 1)) % mod;
                sb = (0ll + sb + T.Query(1, n, 1, id[pu], id[u], 0)) % mod;
                u = pa[pu];
            }
            else {
                sa = (0ll + sa + T.Query(1, n, 1, id[pv], id[v], 1)) % mod;
                sb = (0ll + sb + T.Query(1, n, 1, id[pv], id[v], 0)) % mod;
                v = pa[pv];
            }
            pu = top[u], pv = top[v];
        }
        if (id[u] <= id[v]) {
            sa = (0ll + sa + T.Query(1, n, 1, id[u], id[v], 1)) % mod;
            sb = (0ll + sb + T.Query(1, n, 1, id[u], id[v], 0)) % mod;
        }
        else {
            sa = (0ll + sa + T.Query(1, n, 1, id[v], id[u], 1)) % mod;
            sb = (0ll + sb + T.Query(1, n, 1, id[v], id[u], 0)) % mod;
        }
        return (1ll * sa * sa % mod - 1ll * sb + mod) * (LL)inv2 % mod;
    }
};

TreeCut cut;

int main()
{
    sc(n), sc(m);
    Rep(i, 1, n) sc(v[i]);

    cut.Inite();
    rep(i, 1, n) {
        int u, v;
        sc(u), sc(v);
        cut.addedge(u, v);
    }

    cut.Start();
    while(m--) {
        int op, x, y, z;
        sc(op);
        if (op == 1) {
            sc(x), sc(z);
            T.Update(1, n, 1, id[x], id[x] + sz[x] - 1, z);
        }
        else if (op == 2) {
            sc(x), sc(y), sc(z);
            cut.Update(x, y, z);
        }
        else {
            sc(x), sc(y);
            pr(cut.sum(x, y));
        }
    }
    return 0;
}

 

posted @ 2018-09-13 00:55  天之道,利而不害  阅读(193)  评论(0编辑  收藏  举报