zoukankan      html  css  js  c++  java
  • 2020.7.15模拟赛

    相遇 Railway

    洛谷AC传送门

    题目描述:

    已知我国有 n 座城市,这些城市通过 $n-1$ 条高铁相连。且任意两个城市联通。

    小 A 想从 $x_1$ 号城市出发,到 $y_1$ 号城市,小 B 想从 $x_2$ 号城市出发,到 $y_2$ 号

    城市,问他们是否可能在路途中相遇(出现在同一城市)

    你需要回答 $m$ 次这样的问题。

    输入:

    第一行一个数 $T$,表示数据组数

    对于每一组数据:

    第一行两个数 $n,m$(1 ≤ $n$,$m$ ≤ $100,000$)

    第 $2~n$ 行,每行两个数$ x,y $表示有一条铁路连接城市$ x$ 和 $y$

    接下来 $m$ 行每行四个数,分别表示 $x_1,y_1,x_2,y_2$,表示一次询问

    输出:

    对于每次询问输出 YES 或 NO

    直接求LCA,然后分类讨论啊!

    #include <bits/stdc++.h>
    using namespace std;
    #define N 1000010
    
    inline int read(){
        int x = 0, s = 1;
        char c = getchar();
        while(!isdigit(c)){
            if(c == '-')s = -1;
            c = getchar();
        }
        while(isdigit(c)){
            x = x * 10 + (c - '0');
            c = getchar();
        }
        return x * s;
    }
    
    struct node{
        int v, next;
    } t[N << 1];
    int f[N];
    
    int bian = 0;
    inline void add(int u, int v){
        t[++bian] = (node){v, f[u]}, f[u] = bian;
        t[++bian] = (node){u, f[v]}, f[v] = bian;
        return ;
    }
    
    namespace LCA{
        int fa[N], son[N], siz[N], top[N], deth[N];    
        
        #define v t[i].v
        
        void dfs1(int now, int father){
            siz[now] = 1;
            fa[now]    = father;
            deth[now] = deth[father] + 1;
            for(int i = f[now]; i; i = t[i].next){
                if(v != father){
                    dfs1(v, now);
                    siz[now] += siz[v];
                    if(siz[v] > siz[son[now]])    
                        son[now] = v;
                    }
                }
            return ;
        }
        
        void dfs2(int now, int tp){    
            top[now] = tp;
            if(!son[now]) return ;
            dfs2(son[now], tp);
            for(int i = f[now]; i; i = t[i].next){    
                if(v != fa[now] && v != son[now])
                    dfs2(v, v);
            }
            return ;
        }
        
        #undef v
        
        int lca(int x, int y){
            while(top[x] != top[y]){
                if(deth[top[x]] < deth[top[y]]) swap(x ,y);
                x = fa[top[x]];
            }
            return deth[x] <= deth[y] ? x : y; /*lca肯定是深度比较小(在上面的)的那个*/
        } 
        
        inline void clean(){
            memset(fa, 0, sizeof(fa));
            memset(son, 0, sizeof(son));
            memset(siz, 0, sizeof(siz));
            memset(top, 0, sizeof(top));
            memset(deth, 0, sizeof(deth));
            return ;
        }
        
        inline bool judge(int x1, int y1, int x2, int y2){
            int lca1 = lca(x1 , y1);         
            int lca2 = lca(x2 , y2);
            if(lca1 == lca2) return 1;
            if(deth[lca1] > deth[lca2]){
                if(lca(lca1 , x2) == lca1 || lca(lca1 , y2) == lca1) return 1;
                else return 0;
            }
            else if(deth[lca1] < deth[lca2]){
                if(lca(lca2, x1) == lca2 || lca(lca2, y1) == lca2) return 1;
                else return 0;
            }
            return 0;
        }
        
    }
    
    int n, m;
    
    inline void clean(){
        LCA::clean();
        for(int i = 1;i <= bian; i++){
            t[i] = (node){0,0};
        }
        memset(f, 0, sizeof(f));
        bian = 0;
        return ;
    }
    
    
    
    int main(){
    //    freopen("railway.in", "r", stdin);
    //    freopen("railway.out", "w", stdout);
        int T = read();
        while(T--){
            clean();
            n = read(), m = read();
            for(int i = 1;i < n; i++){
                int x = read(), y = read();
                add(x, y);
            }
            LCA::dfs1(1, 1);
            LCA::dfs2(1, 1);
            for(int i = 1;i <= m; i++){
                int a = read(), b = read(), c = read(), d = read();
                 if(LCA::judge(a, b, c, d)) printf("YES
    ");
                 else printf("NO
    ");
            }
        }
        return 0;
    }

    计数 Count

    洛谷AC传送门

    推公式:

    设$maxn_{l,r}$表示$l$ ~ $r$的最大值,$minn_{l,r}$表示$l$ ~ $r$的最小值。

    那么,我们有

    $ans = Σ_{l=1}^nΣ_{r=l}^n maxn_{l,r} - Σ_{l=1}^nΣ_{r=l}^n minn_{l,r} $

    考虑将两部分分开来求:

    对于一个数字$a_i$, 我们设$l_i$ 为左边第一个比它的数的位置,$r_i$为右边第一个比它大的位置,那么,则有:

    $Σ_{l=1}^nΣ_{r=l}^n maxn_{l,r}$ $=$  $Σ_{i=1}^n (r_i - i) * (i - l_i) * a[i]$

    原因:

    一个数能管辖的范围,即为从$l_i$到$i$, $i$ 到$r_i$的所有区间

    那么,对于最小值,也是一模一样的式子,只不过是将$l_i$, $r_i$换成最小值而已

    #include <bits/stdc++.h>
    using namespace std;
    #define N 100010
    #define ll long long
    
    inline ll read(){
        ll x = 0, s = 1;
        char c = getchar();
        while(!isdigit(c)){
            if(c == '-')s = -1;
            c = getchar();
        }
        while(isdigit(c)){
            x = x * 10 + (c ^ '0');
            c = getchar();
        }
        return x * s;
    }
    
    ll l[N], r[N];
    ll a[N];
    ll ans = 0;
    
    inline void clear(int n){
        memset(l, 0, sizeof(l));
        for(ll i = 1;i <= n; i++)r[i] = n + 1;
        return ;
    }
    
    int main(){
        int T = read();
        while(T--){
            ans = 0;
            int n = read();
            clear(n);
            for(int i = 1;i <= n; i++)
                a[i] = read();
            for(int i = 1;i <= n; i++){
                for(int j = i - 1; j > 0; j--){
                    if(a[j] > a[i]){
                        l[i] = j;
                        break; 
                    }
                }
                for(int j = i + 1;j <= n; j++){
                    if(a[j] > a[i]){
                        r[i] = j;
                        break;
                    }
                }
            }
            for(int i = 1;i <= n; i++)
                ans += (r[i] - i) * (i - l[i]) * a[i];
            clear(n);
            for(int i = 1;i <= n; i++){
                for(int j = i - 1; j > 0; j--){
                    if(a[j] < a[i]){
                        l[i] = j;
                        break; 
                    }
                }
                for(int j = i + 1;j <= n; j++){
                    if(a[j] < a[i]){
                        r[i] = j;
                        break;
                    }
                }
            }
            for(int i = 1;i <= n; i++)
                 ans -= (r[i] - i) * (i - l[i]) * a[i];
            cout << ans << endl;
        }
        return 0;
    }
  • 相关阅读:
    使用SO_REVTIMEO套接字选项为recvfrom设置超时
    使用select为描述符设置超时
    套接字超时设置方法
    使用SIGALARM为recvfrom设置超时
    使用SIGALARM为connect设置超时
    20200410 阿里巴巴Java开发手册
    20200409 Vue 视频学习【归档】
    20200319 Spring MVC 官方文档【归档】
    20200319 Spring Web MVC 2-5
    20200319 Spring Web MVC 1
  • 原文地址:https://www.cnblogs.com/wondering-world/p/13333966.html
Copyright © 2011-2022 走看看