18寒假第四测

Posted Ed_Sheeran

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了18寒假第四测相关的知识,希望对你有一定的参考价值。

problem 4 full

第一题:裸的树状数组

#include <cstdio>

const int N = 100010;
const int M = N + N;

int n, q;
int aa[N];
int head[N], dest[M], last[M], etot;
int in[N], out[N], seq[N], idc;
long long bit[N];

void adde( int u, int v ) {
    etot++;
    dest[etot] = v;
    last[etot] = head[u];
    head[u] = etot;
}
void dfs( int u, int f ) {
    idc++;
    in[u] = idc;
    seq[idc] = u;
    for( int t = head[u]; t; t = last[t] ) {
        int v = dest[t];
        if( v == f ) continue;
        dfs( v, u );
    }
    out[u] = idc;
}
void modify( int pos, int delta ) {
    for( int i = pos; i <= n; i += i & -i )
        bit[i] += delta;
}
long long query( int rg ) {
    long long rt = 0;
    for( int i = rg; i; i -= i & -i) {
        rt += bit[i];
    }
    return rt;
}
long long query( int lf, int rg ) {
    return query(rg) - query(lf-1);
}
int main() {
    freopen("subtree.in", "r", stdin);
    freopen("subtree.out", "w", stdout);
    scanf( "%d", &n );
    for( int i = 1; i <= n; i++ )
        scanf( "%d", aa + i );
    for( int i = 1; i < n; i++ ) {
        int u, v;
        scanf( "%d%d", &u, &v );
        adde( u, v );
        adde( v, u );
    }
    idc = 0;
    dfs(1,1);
    for( int u = 1; u <= n; u++ ) {
        modify( in[u], aa[u] );
    }
    scanf( "%d", &q );
    while( q-- ) {
        char ss[100];
        int u, d;
        scanf( "%s", ss );
        if( ss[0] == \'m\' ) {
            scanf( "%d%d", &u, &d );
            modify( in[u], d );
        } else {
            scanf( "%d", &u );
            printf( "%lld\\n", query( in[u], out[u] ) );
        }
    }
}

 

第二题:裸的树剖求LCA

#include<bits/stdc++.h>
using namespace std;
const int maxn = 100005;
int a[maxn],head[maxn * 2],to[maxn * 2],next[maxn * 2];//2倍空间
int son[maxn], f[maxn], siz[maxn], top[maxn], dep[maxn];
int n, tot, idx, m;
void adde(int u, int v){
    ++tot;
    next[tot] = head[u];
    to[tot] = v;
    head[u] = tot;
}

void dfs1(int u,int from){
    siz[u] = 1;
    
    for(int i = head[u]; i; i = next[i]){
        int v = to[i];
        if(v != from){
        
            f[v] = u;
            dep[v] = dep[u] + 1;
            dfs1(v, u);
            siz[u] += siz[v];            
            if(siz[v] > siz[son[u]])
                son[u] = v;
        }
    }
}
void dfs2(int u,int from){
    
    top[u] = from;
    if(son[u])dfs2(son[u], from);
    for(int i = head[u]; i; i = next[i]){
        int v = to[i];
        if(v == f[u] || v == son[u])continue;//f[u] != from    !
        dfs2(v, v);
    }
}

int lca(int u, int v){
    while(top[u] != top[v]){
        if(dep[top[u]] < dep[top[v]])swap(u, v);//dep[top]   !
        u = f[top[u]];
    }
    return dep[u] < dep[v] ? u : v;
}
int main(){
    freopen("dcplca.in","r",stdin);
    freopen("dcplca.out","w",stdout);
    //ios::sync_with_stdio(false);
    cin>>n;
    for(int i = 1; i < n; i++){
        int u, v;
        scanf("%d%d",&u,&v);
        adde(u, v);
        adde(v, u);
    }
    dep[1] = f[1] =1;
    dfs1(1, 1);
    dfs2(1, 1);
    cin>>m;
    for(int i = 1; i <= m; i++){
        int u,v;
        scanf("%d%d",&u,&v);
        printf("%d\\n",lca(u, v));
        
    }
}

 

第三题:线段树+树剖

 

#include<bits/stdc++.h>
using namespace std;
const int maxn = 100005;
long long c[maxn];
int a[maxn],head[maxn * 2],to[maxn * 2],next[maxn * 2];
int son[maxn], in[maxn], out[maxn], f[maxn], siz[maxn], top[maxn], dep[maxn];
int n, tot, idx, m;

void adde(int u, int v){
    ++tot;
    next[tot] = head[u];
    to[tot] = v;
    head[u] = tot;
}

struct SegmentTree{
    struct node{
        long long sum;
        int lazy; 
    };
    node Tree[maxn << 2];
    
    #define ls l, m, v << 1
    #define rs m+1, r, v << 1 | 1
    
    void push_up(int v){

        Tree[v].sum = Tree[v << 1].sum + Tree[v << 1 | 1].sum;
    }
    void push_down(int l,int r,int v){
        int m = (l + r) >> 1;
        Tree[v << 1].sum += 1LL * Tree[v].lazy * (m - l + 1);
        Tree[v << 1].lazy += Tree[v].lazy;
        Tree[v << 1 | 1].sum += 1LL * Tree[v].lazy * (r - m);
        Tree[v << 1 | 1].lazy += Tree[v].lazy;
        
        Tree[v].lazy = 0;
        
    }
    void build(int l = 1, int r = n, int v = 1){
        Tree[v].sum = Tree[v].lazy = 0;
        if(l == r) {
            Tree[v].sum = a[l] * 1LL;
            Tree[v].lazy = 0;
        }
        else {
            int m = (l + r) >> 1;
            build(ls);
            build(rs);
            push_up(v);
        }
    }
    
    void modify(int x,int L,int R,int l = 1, int r = n,int v = 1){
        if(l >= L && r <= R)
            Tree[v].sum += 1LL * x * (r - l + 1), Tree[v].lazy += x;
        else {
            if(Tree[v].lazy)push_down(l,r,v);
            int m = (l + r) >> 1;
            if(L <= m) modify(x,L,R,ls);
            if(R > m) modify(x,L,R,rs);
            push_up(v);
        }
    }

    long long  query(int L,int R,int l = 1, int r = n,int v = 1){
        if(l >= L && r <= R)
            return Tree[v].sum ;
        else {
            if(Tree[v].lazy)push_down(l,r,v);
            int m = (l + r) >> 1;
            long long ans = 0;
            if(L <= m) ans += query(L,R,ls);
            if(R > m) ans += query(L,R,rs);
            return ans;
        }
    }
    
}; 

SegmentTree Tr;

void dfs1(int u,int from){
    siz[u] = 1;
    for(int i = head[u]; i; i = next[i]){
        int v = to[i];
        if(v != from){        
            f[v] = u;
            dep[v] = dep[u] + 1;
            dfs1(v, u);
            siz[u] += siz[v];            
            if(siz[v] > siz[son[u]])
                son[u] = v;
        }
    }
    
}

void dfs2(int u,int from){
    in[u] = ++idx;
    a[idx] = c[u];
    top[u] = from;
    if(son[u])dfs2(son[u], from);
    for(int i = head[u]; i; i = next[i]){
        int v = to[i];
        if(v == f[u] || v == son[u])continue;//f[u] != from !
        dfs2(v, v);
    }
    out[u] = idx;
}

long long lca1(int u, int v){
    long long ans = 0;
    while(top[u] != top[v]){
        if(dep[top[u]] < dep[top[v]])//dep[top]!
            swap(u, v);
        ans += Tr.query(in[top[u]], in[u]);
        u = f[top[u]];
    }
    if(dep[u] < dep[v])swap(u,v);
    ans += Tr.query(in[v], in[u]);
    return  ans;
}

void lca2(int u, int v,int x){
    long long ans = 0;
    while(top[u] != top[v]){
        if(dep[top[u]] < dep[top[v]])//dep[top]!
            swap(u, v);
        Tr.modify(x, in[top[u]], in[u]);
        u = f[top[u]];
    }
    if(dep[u] < dep[v])swap(u,v);
    Tr.modify(x, in[v], in[u]);
}

void init(){
    
    cin>>n;
    for(int i = 1; i <= n; i++)
        scanf("%d",c + i);
    for(int i = 1; i < n; i++){
        int u, v;
        scanf("%d%d",&u,&v);
        adde(u, v);
        adde(v, u);
    }
    dep[1] = f[1] = 1;
    dfs1(1,1);
    dfs2(1,1);
    Tr.build();
}

void work(){
    cin>>m;
    for(int i = 1; i <= m; i++){
        string opt;
        cin>>opt;
        if(opt == "msub"){
            int u,x;
            scanf("%d%d",&u,&x);
            Tr.modify(x,in[u],out[u]);
        }
        if(opt == "mpth"){
            int u,x,v;            
            scanf("%d%d%d",&u,&v,&x);
            lca2(u,v,x);

        }
        if(opt == "qsub"){
            int u;
            scanf("%d",&u);
            cout<<Tr.query(in[u],out[u])<<endl;
        }
        if(opt == "qpth"){
            int u,v;
            scanf("%d%d",&u,&v);
            cout<<lca1(u, v)<<endl;
        }
        
    }
}
int main(){
    freopen("full.in","r",stdin);
    freopen("full.out","w",stdout);
    init();
    work();
}

 

以上是关于18寒假第四测的主要内容,如果未能解决你的问题,请参考以下文章

开学第四测

暑假第四测

NOI十连测 第四测 T3

NOI十连测 第四测 T1

寒假第四次作业

2018年全国多校算法寒假训练营练习比赛(第四场)-A石油采集(匈牙利算法)