zoukankan      html  css  js  c++  java
  • 【题解】CF#960 H-Santa's Gift

      好久没有写过数据结构题目了,果然还是太不自信。实际上就是要求统计一个式子:

      (sum (c[k]*p[k] - C)^{2})

    拆开,分别统计和与平方和

    (co[k] * sum p[k]^{2} - 2 * C * co[k] sum p[k] + sum C ^{2})

    显然可以用树链剖分 + 线段树维护

    平方和在区间 + 1的时候直接用 ((x + 1) ^ {2} = x^2 + 2 * x + 1) 计算即可。

      至于不同的口味的问题,我们给每个口味都开一线段树,动态开点~听起来虽然复杂,但代码实际上超短。◕ᴗ◕。

    #include <bits/stdc++.h>
    using namespace std;
    #define maxn 3000000
    #define int long long 
    #define db double
    int n, m, q, C, cnt, f[maxn], co[maxn], dfn[maxn];
    int size[maxn], hson[maxn], top[maxn], fa[maxn];
    int root[maxn], mark[maxn * 2], cal[maxn * 2], cal2[maxn * 2], son[maxn * 2][2];
    
    int read()
    {
        int x = 0, k = 1;
        char c; c = getchar();
        while(c < '0' || c > '9') { if(c == '-') k = -1; c = getchar(); }
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return x * k;
    }
    
    struct edge
    {
        int cnp, to[maxn], last[maxn], head[maxn];
        edge() { cnp = 2; }
        void add(int u, int v)
        { to[cnp] = v, last[cnp] = head[u], head[u] = cnp ++; }
    }E1;
    
    void dfs(int u)
    {
        size[u] = 1; int mx = 0, hs = 0;
        for(int i = E1.head[u]; i; i = E1.last[i])
        {
            int v = E1.to[i];
            fa[v] = u; dfs(v); size[u] += size[v];
            if(size[v] >= mx) mx = size[v], hs = v;
        }
        hson[u] = hs;
    }
    
    void dfs2(int u, int anc)
    {
        dfn[u] = ++ cnt, top[u] = anc;
        if(hson[u]) dfs2(hson[u], anc);
        for(int i = E1.head[u]; i; i = E1.last[i])
            if(E1.to[i] != hson[u]) dfs2(E1.to[i], E1.to[i]);
    }
    
    void Add(int &p, int l, int r, int x)
    {
        if(!p) p = ++ cnt; mark[p] += x;
        cal2[p] += cal[p] * x + (r - l + 1) * x * x; 
        cal[p] += (r - l + 1) * x * 2;
    }
    
    void Push_down(int p, int l, int r)
    {
        int mid = (l + r) >> 1;
        if(!mark[p]) return;
        Add(son[p][0], l, mid, mark[p]); Add(son[p][1], mid + 1, r, mark[p]);
        mark[p] = 0;
    }
    
    void Push_Up(int p)
    {
        int l = son[p][0], r = son[p][1];
        cal2[p] = cal2[l] + cal2[r]; cal[p] = cal[l] + cal[r];
    }
    
    void Update(int &p, int l, int r, int L, int R, int x)
    {
        if(L > R || l > r) return;
        if(!p) p = ++ cnt;
        if(L <= l && R >= r) { Add(p, l, r, x); return; }
        Push_down(p, l, r); int mid = (l + r) >> 1;
        if(L <= mid) Update(son[p][0], l, mid, L, R, x); 
        if(R > mid) Update(son[p][1], mid + 1, r, L, R, x);
        Push_Up(p);    
    }
    
    void T_Update(int k, int u, int x)
    {
        for(; u; u = fa[top[u]])
            Update(root[k], 1, n, dfn[top[u]], dfn[u], x);
    }
    
    int Cal(int p) 
    { return co[p] * co[p] * cal2[root[p]] - cal[root[p]] * C * co[p] + n * C * C; }
    
    signed main()
    {
        n = read(), m = read(), q = read(), C = read();
        for(int i = 1; i <= n; i ++) f[i] = read();
        for(int i = 2; i <= n; i ++) { int x = read(); E1.add(x, i); }
        for(int i = 1; i <= m; i ++) co[i] = read();
        dfs(1), dfs2(1, 1), cnt = m;
        for(int i = 1; i <= m; i ++) root[i] = i;
        for(int i = 1; i <= n; i ++) T_Update(f[i], i, 1);
        for(int i = 1; i <= q; i ++)
        {
            int opt = read();
            if(opt == 1) 
            {
                int x = read(), k = read();
                T_Update(f[x], x, -1), T_Update(f[x] = k, x, 1); 
            }
            else 
            {
                int k = read();
                printf("%lf
    ", (db) Cal(k) / (db) n);
            }
        }
        return 0;
    }
  • 相关阅读:
    关于学习netty的两个完整服务器客户端范例
    android-betterpickers
    ValueBar
    CircleDisplay
    JellyViewPager
    十天学习PHP之第二天
    android-測试so动态库(九)
    实习题
    android 编程小技巧(持续中)
    Codeforces Round #253 (Div. 2)——Borya and Hanabi
  • 原文地址:https://www.cnblogs.com/twilight-sx/p/9760398.html
Copyright © 2011-2022 走看看