zoukankan      html  css  js  c++  java
  • 牛客练习赛14 B 倍增 E bitset

    B 区间的连续段
    链接:https://www.nowcoder.com/acm/contest/82/B
    来源:牛客网

    题目描述

    给你一个长为n的序列a和一个常数k

    有m次询问,每次查询一个区间[l,r]内所有数最少分成多少个连续段,使得每段的和都 <= k

    如果这一次查询无解,输出"Chtholly"
    输入描述:

    第一行三个数n,m,k
    第二行n个数表示这个序列a
    之后m行,每行给出两个数l r表示一次询问

    输出描述:

    输出m行,每行一个整数,表示答案

    示例1
    输入

    5 5 7
    2 3 2 3 4
    3 3
    4 4
    5 5
    1 5
    2 4

    输出

    1
    1
    1
    2
    2

    备注:

    对于100%的数据,1 <= n , m <= 1000000 , 1 <= ai , k <= 1000000000

    tags:
    dp[i][j] 表示第 i 个数往后走 2^j 段能到达第几个数,所以转移即 dp[i][j] = dp[dp[i][j-1]][j-1] ,查询时只要倍增跳着找即可。

    //https://www.nowcoder.com/acm/contest/82/B
    #include<bits/stdc++.h>
    using namespace std;
    #pragma comment(linker, "/STACK:102400000,102400000")
    #define rep(i,a,b) for (int i=a; i<=b; ++i)
    #define per(i,b,a) for (int i=b; i>=a; --i)
    #define mes(a,b)  memset(a,b,sizeof(a))
    #define INF 0x3f3f3f3f
    #define MP make_pair
    #define PB push_back
    #define fi  first
    #define se  second
    #define  mid  (l+(r-l)/2)
    typedef long long ll;
    const int N = 1000005;
    
    int n, m, dp[N][21], k, a[N];
    ll  sum[N];
    int solve(int l, int r) {
        int ret = 1;
        for(int j=20; dp[l][0]<=r; --j) {
            if(dp[l][j]<=r) {
                l = dp[l][j];
                ret += (1<<j);
            }
        }
        return ret;
    }
    int vis[N];
    int main()
    {
        scanf("%d%d%d", &n, &m, &k);
        int ai;
        rep(i,1,n) {
            scanf("%d", &a[i]), sum[i]=sum[i-1]+a[i];
            vis[i] = vis[i-1]+(a[i]>k);
        }
        mes(dp, INF);
        rep(i,1,n)
        {
            int pos = upper_bound(sum+1, sum+1+n, sum[i-1]+k) - sum;
            dp[i][0] = pos;
        }
        for(int j=0; (1<<j)<=n; ++j)
        {
            rep(i,1,n)
            {
                if(dp[i][j-1]<=n)
                    dp[i][j] = dp[dp[i][j-1]][j-1];
            }
        }
        int l, r;
        while(m--)
        {
            scanf("%d%d", &l, &r);
            if(vis[r]-vis[l-1]>0) puts("Chtholly");
            else printf("%d
    ", solve(l, r));
        }
    
        return 0;
    }
    
    

    E 无向图中的最短距离
    链接:https://www.nowcoder.com/acm/contest/82/E
    来源:牛客网

    题目描述

    有一个n个点的无向图,有m次查询,每次查询给出一些(xi,yi)

    令dist(x,y)表示x和y点在图中最短距离,dist(x,x)=0,如果x,y不连通则dist(x,y) = inf

    每次查询图中有多少个点v与至少一个这次询问给出的(xi,yi)满足dist(v,xi)<=yi
    输入描述:

    第一行三个数表示n,m,q

    之后m行每行两个数x,y表示有一条x与y之间的边,边权为1

    之后q次询问,每个询问先给你一个数a
    之后一行2a个数,第2i-1个数xi和第2i个数yi表示一个二元组(xi,yi)

    输出描述:

    输出q行,每行一个数表示这次询问的答案

    示例1
    输入

    5 6 6
    2 3
    1 3
    2 5
    1 3
    3 2
    2 5
    1
    3 1
    1
    1 1
    1
    1 4
    1
    5 2
    1
    1 4
    2
    1 0 5 1

    输出

    3
    2
    4
    3
    4
    3

    备注:

    对于100%的数据,n <= 1000 , m <= 100000 , q <=
    100000
    a的和<= 2100000

    tags:
    先预处理出每个点到其它 n-1个点的最短距离,然后搞个 bitset<1000>bit[1000][1000] ,比如到点 u 的距离 <= x 的点 to 存入,即 bit[u][x].set(to) ,也就是把距离 <= 或者 > 两种可能性存入进去。 bitset 是按位储存的, bitset<1000> 只有1000位(实际应该会按字节扩充一点),所以是可以储存下的。

    //https://www.nowcoder.com/acm/contest/82/E
    #include<bits/stdc++.h>
    using namespace std;
    #pragma comment(linker, "/STACK:102400000,102400000")
    #define rep(i,a,b) for (int i=a; i<=b; ++i)
    #define per(i,b,a) for (int i=b; i>=a; --i)
    #define mes(a,b)  memset(a,b,sizeof(a))
    #define INF 0x3f3f3f3f
    #define MP make_pair
    #define PB push_back
    #define fi  first
    #define se  second
    typedef long long ll;
    const int N = 1005;
    
    bitset<N> bit[N][N], bit1;
    int n, m;
    vector< int > G[N];
    
    int dis[N];  bool inq[N];  queue< int > q;
    void spfa(int st)
    {
        while(!q.empty()) q.pop();
        mes(dis, INF);
        dis[st] = 0;
        q.push(st);
        while(!q.empty())
        {
            int u = q.front();  q.pop();
            inq[u] = false;
            for(int to : G[u])
            {
                if(dis[to] > dis[u]+1)
                {
                    dis[to] = dis[u]+1;
                    if(inq[to]==false) inq[to]=true, q.push(to);
                }
            }
        }
        rep(i,1,n) if(dis[i]!=INF) bit[st][dis[i]].set(i);
        rep(i,1,n) bit[st][i] |= bit[st][i-1];
    }
    int main()
    {
        int Q;
        scanf("%d%d%d", &n, &m, &Q);
        int u, v;
        rep(i,1,m)
        {
            scanf("%d%d", &u, &v);
            G[u].PB(v), G[v].PB(u);
        }
        rep(i,1,n) spfa(i);
        int k, x, y;
        while(Q--)
        {
            bit1.reset();
            scanf("%d", &k);
            while(k--)
            {
                scanf("%d%d", &x, &y);
                bit1 |= bit[x][y];
            }
            printf("%d
    ", bit1.count());
        }
    
        return 0;
    }
    
    
  • 相关阅读:
    hdu 2485 Destroying the bus stations 迭代加深搜索
    hdu 2487 Ugly Windows 模拟
    hdu 2492 Ping pong 线段树
    hdu 1059 Dividing 多重背包
    hdu 3315 My Brute 费用流,费用最小且代价最小
    第四天 下载网络图片显示
    第三天 单元测试和数据库操作
    第二天 布局文件
    第一天 安卓简介
    Android 获取存储空间
  • 原文地址:https://www.cnblogs.com/sbfhy/p/8732884.html
Copyright © 2011-2022 走看看