• 四连测Day1


    一道大暴力被人说做法雷同...真的是醉了

    T1 树上路径最小值(min)

    给一棵树,多次询问两点间路径上点权最小值

    sol:树链剖分 倍增 平衡树(划掉)

    瞎J2乱做都可以

    然而太困了爆零

    #include<bits/stdc++.h>
    using namespace std;
    inline int read()
    {
        int x = 0,f = 1;char ch = getchar();
        for(;!isdigit(ch);ch = getchar())if(ch == '-') f = -f;
        for(;isdigit(ch);ch = getchar())x = 10 * x + ch - '0';
        return x * f;
    }
    const int maxn = 1e5 + 777;
    int n;
    int first[maxn],to[maxn << 1],next[maxn << 1],cnt;
    int a[maxn],size[maxn],bl[maxn],fa[maxn],depth[maxn],dfn;
    int pos[maxn],reh[maxn];
    inline void add(int u,int v)
    {
        to[++cnt] = v;next[cnt] = first[u];first[u] = cnt;
    }
    inline void ins(int u,int v){add(u,v);add(v,u);}
    inline void dfs1(int u)
    {
        size[u] = 1;
        for(int i=first[u];i;i=next[i])
        {
            if(to[i] == fa[u])continue;
            fa[to[i]] = u;dfs1(to[i]);depth[to[i]] = depth[u] + 1;size[u] += size[to[i]];
        }
    }
    inline void dfs2(int u,int col)
    {
        int k = 0;pos[u] = ++dfn;reh[pos[u]] = u;bl[u] = col;
        for(int i=first[u];i;i=next[i])
            if(to[i] != fa[u] && size[to[i]] > size[k])k = to[i];
        if(!k)return;
        dfs2(k,col);
        for(int i=first[u];i;i=next[i])
            if(to[i] != fa[u] && k != to[i])dfs2(to[i],to[i]);
    }
    int seg[maxn << 2];
    #define ls (x << 1)
    #define rs ((x << 1) | 1)
    inline void update(int x,int l,int r,int pos,int val)
    {
        if(l == r)
        {
            seg[x] = val;
            return;
        }
        int mid = (l + r) >> 1;
        if(pos <= mid)update(ls,l,mid,pos,val);
        else update(rs,mid + 1,r,pos,val);
        seg[x] = min(seg[ls],seg[rs]);
    }
    inline int query(int x,int l,int r,int L,int R)
    {
        if(L <= l && r <= R)return seg[x];
        int mid = (l + r) >> 1,ans = 2147483233;
        if(L <= mid)ans = min(ans,query(ls,l,mid,L,R));
        if(R > mid)ans = min(ans,query(rs,mid + 1,r,L,R));
        return ans;
    }
    
    int main()
    {
        freopen("min.in","r",stdin);
        freopen("min.out","w",stdout);
        int q;
        for(int i=1;i<maxn * 4;i++)seg[i] = 2147483233;
        n = read();q = read();
        for(int i=1;i<=n;i++)a[i] = read();
        for(int i=2;i<=n;i++)
        {
            int u = read(),v = read();
            ins(u,v);
        }dfs1(1);dfs2(1,1);
        for(int i=1;i<=n;i++)update(1,1,n,pos[i],a[i]);
        while(q--)
        {
            int u = read(),v = read();int ans = 2147483233;
            while(bl[u] != bl[v])
            {
                if(depth[bl[u]] < depth[bl[v]])swap(u,v);
                ans = min(ans,query(1,1,n,pos[bl[u]],pos[u]));
                u = fa[bl[u]];
            }
            if(pos[u] > pos[v])swap(u,v);
            ans = min(ans,query(1,1,n,pos[u],pos[v]));
            printf("%d
    ",ans);
        }
    }
    爆炸代码(0分)
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #define MAXN 131072
    using namespace std;
    inline int read()
    {
        int x=0,t=1,c;
        while(!isdigit(c=getchar()))if(c=='-')t=-1;
        while(isdigit(c))x=x*10+c-'0',c=getchar();
        return x*t;
    }
    int n,q;
    int a[MAXN];
    int first[MAXN],targ[MAXN<<1],nxt[MAXN<<1],cnte=1;
    int anc[MAXN][22],minv[MAXN][22],deep[MAXN];
    void AddEdge(int u,int v)
    {
        targ[cnte]=v;nxt[cnte]=first[u];first[u]=cnte++;swap(u,v);
        targ[cnte]=v;nxt[cnte]=first[u];first[u]=cnte++;
    }
    void DFS(int x=1,int Fa=0)
    {
        anc[x][0]=Fa;
        minv[x][0]=min(a[x],a[Fa]);
        for(int i=1;i<20;i++)
        {
            anc[x][i]=anc[anc[x][i-1]][i-1];
            minv[x][i]=min(minv[x][i-1],minv[anc[x][i-1]][i-1]);
        }
        for(int i=first[x];i;i=nxt[i])
        {
            if(targ[i]!=Fa)
            {
                deep[targ[i]]=deep[x]+1;
                DFS(targ[i],x);
            }
        }
    }
    void Jump(int &x,int f,int &r)
    {
        r=min(r,minv[x][f]);
        x=anc[x][f];
    }
    int LCA(int x,int y)
    {
        int ret=min(a[x],a[y]);
        if(deep[x]<deep[y])swap(x,y);
        for(int i=19;i>=0;i--)
        {
            if((1<<i)<=deep[x]-deep[y])Jump(x,i,ret);
        }
        for(int i=19;i>=0;i--)if(anc[x][i]!=anc[y][i])Jump(x,i,ret),Jump(y,i,ret);
        if(x!=y)Jump(x,0,ret),Jump(y,0,ret);
        //printf("%d %d
    ",x,y);
        return ret;
    }
    int main()
    {
        freopen("min.in","r",stdin);
        freopen("min.out","w",stdout);
        n=read(),q=read();
        for(int i=1;i<=n;i++)a[i]=read();
        for(int i=1;i<n;i++)AddEdge(read(),read());
        deep[1]=1;
        DFS();
        for(int i=0;i<q;i++)
        {
            printf("%d
    ",LCA(read(),read()));
        }
    }
    /*
    7 7
    1 2 3 4 5 6 7
    1 2
    2 4
    3 2
    4 6
    5 6
    6 7
    1 7
    2 6
    3 5
    1 2
    3 4
    5 6
    4 7
    */
    std

    T2 k大异或和

    给一个数组a,求a中第k小的非空子序列异或和

    n<=1e4

    sol:记录一下当前的是第几大,具体可以通过一个桶前缀和来搞,然后upperbound

    高二的几个小伙伴都是这么写的于是被D了

    标算是桶排序。。。

    无语

    #include<bits/stdc++.h>
    using namespace std;
    inline int read()
    {
        int x = 0,f = 1;char ch = getchar();
        for(;!isdigit(ch);ch = getchar())if(ch == '-') f = -f;
        for(;isdigit(ch);ch = getchar())x = 10 * x + ch - '0';
        return x * f;
    }
    const int maxn = 1e4 + 10;
    int n,q,k;
    int a[maxn],s[maxn];
    int sum[1049000];
    int main()
    {
        freopen("xor.in","r",stdin);
        freopen("xor.out","w",stdout);
        n = read(),q = read();
        for(int i=1;i<=n;i++)a[i] = read(),s[i] = s[i - 1] ^ a[i];
        for(int i=0;i<n;i++)
            for(int j=i + 1;j<=n;j++)sum[s[i] ^ s[j]]++;
        for(int i=1;i<=1048576;i++)sum[i] += sum[i - 1];
        while(q--)
        {
            int k = read();
            printf("%d
    ",upper_bound(sum,sum + 1048576,k - 1) - sum);
        }
    }
    View Code

    T3 最小生成树

    给n个点,m条计划,每条计划是在[l,r]中任意点连边

    每连一条边需要vi的代价

    求把所有点连通的最小代价

    sol:线段树 + 贪心

    发现连的边一定是当前vi最小的边,于是把计划按vi从大到小排序,每次区间覆盖,最后输出一下整棵树的和就可以了

    #include<bits/stdc++.h>
    using namespace std;
    inline int read()
    {
        int x = 0,f = 1;char ch = getchar();
        for(;!isdigit(ch);ch = getchar())if(ch == '-') f = -f;
        for(;isdigit(ch);ch = getchar())x = 10 * x + ch - '0';
        return x * f;
    }
    const int maxn = 1e5 + 10;
    int n,q;
    int tag[maxn << 2],sum[maxn << 2],vis[maxn << 2];
    struct proj
    {
        int l,r,v;
        bool operator < (const proj &b)const
        {
            return v > b.v;
        }
    }p[maxn];
    #define ls (x << 1)
    #define rs ((x << 1) | 1)
    inline void pushup(int x)
    {
        sum[x] = sum[ls] + sum[rs];
    }
    inline void pushdown(int x,int l,int r)
    {
        if(tag[x])
        {
            int mid = (l + r) >> 1;
            tag[ls] = tag[x];tag[rs] = tag[x];
            sum[ls] = tag[x] * (mid - l + 1);sum[rs] = tag[x] * (r - mid);
            tag[x] = 0;
        }
        if(vis[x])vis[ls] = vis[rs] = 1;
    }
    inline void update(int x,int l,int r,int L,int R,int val)
    {
        if(L <= l && r <= R)
        {
            tag[x] = val;
            sum[x] = val * (r - l + 1);
            vis[x] = 1;
            return;
        }
        pushdown(x,l,r);
        int mid = (l + r) >> 1;
        if(L <= mid)update(ls,l,mid,L,R,val);
        if(mid < R)update(rs,mid + 1,r,L,R,val);
        sum[x] = sum[ls] + sum[rs];
        vis[x] = vis[ls] & vis[rs];
    }
    int main()
    {
        freopen("kruskal.in","r",stdin);
        freopen("kruskal.out","w",stdout);
        n = read() - 1,q = read();
        for(int i=1;i<=q;i++)p[i].l = read(),p[i].r = read() - 1,p[i].v = read();
        sort(p + 1,p + q + 1);
        int ans = 0;
        for(int i=1;i<=q;i++)update(1,1,n,p[i].l,p[i].r,p[i].v);
        if(!vis[1])cout<<-1;
        else cout<<sum[1];
    }
    View Code

    orz

    诅咒:树剖永远写挂

    我真是!$^$&!&*!%*%&*!*&$!&

    upd:有人引用了我的题解

    他好懒

    但是他ak了

    太强了

    %%%

  • 相关阅读:
    在Visual Studio中怎样快速添加代码段
    18个不常见的C#关键字,您使用过几个?
    C# 非常好用的组元Tuple
    C# List根据另一个List集合或数组排序
    Expression 核心操作符、表达式、操作方法
    如何避免频繁创建临时对象
    C# 23种设计模式
    C# 23种设计模式
    Api Cloud官方日期类型转换
    sql server 保留小数(续A)
  • 原文地址:https://www.cnblogs.com/Kong-Ruo/p/9436751.html
Copyright © 2020-2023  润新知