• [ 2020牛客NOIP赛前集训营-提高组(第六场) ] 补题


    B.艰难睡眠

    Problem

    题目链接

    Solution

    • 单调队列

    • 段环成链思想

    明显题目是要我们分别做 n 次单调队列,考虑如何写最方便。

    思考后可以发现,题目中长度为 (k) 的睡眠段在移动,我们可以选择的数区间是一个长度为 (m-k-b[i]+1) 的区间。断环成链后,将跑一个长度为 (m-k-b[i]+1),的区间的滑动窗口,若该区间的右端点为 (r),则对应的睡眠段起点为 (r+b[i])

    Code

    Talk is cheap.Show me the code.

    #include<bits/stdc++.h>
    #define INF 0x3f3f3f3f
    using namespace std;
    inline int read() {
        int x = 0, f = 1; char ch = getchar();
        while(ch<'0' || ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
        while(ch>='0'&&ch<='9') { x=(x<<3)+(x<<1)+(ch^48); ch=getchar(); }
        return x * f;
    }
    const int N = 5007, M = 2007;
    int n,m,k;
    int b[N],c[N][M],ans[M];
    struct Node {
    	int val,t;
    }q[M<<1];
    int main()
    {
    	//freopen("test.in","r",stdin);
    	n = read(), m = read(), k = read();
    	for(int i=1;i<=n;++i) {
    		int tmp = read(); b[i] = read();
    	}
    	for(int i=1;i<=n;++i)
    		for(int j=1;j<=m;++j) c[i][j] = read();
    	for(int i=1;i<=n;++i) {
    		if(b[i]+k > m) {
    			puts("-1"); return 0;
    		}
    	}
    	for(int t=1;t<=n;++t) {
    		int L = 1, R = 0;
    		int len = m - k - b[t] + 1;
    		for(int i=1;i<=2*m;++i) {
    			int now = c[t][(i-1) % m + 1];
    			while(L<=R && q[L].t<=i-len) ++L;
    			while(L<=R && q[R].val>=now) --R;
    			q[++R] = (Node)<%now, i%>;
    			if(i > m) ans[(i + b[t] - 1) % m + 1] += q[L].val;
    		}
    	}
    	int res = INF;
    	for(int i=1;i<=m;++i) res = min(res, ans[i]);
    	printf("%d
    ",res);
        return 0;
    }
    /*
    3 10 6
    3 1
    2 1
    2 3
    4 4 8 5 1 2 2 2 6 4 
    9 3 7 5 7 1 5 2 2 8 
    8 2 7 7 4 9 2 3 4 3 
    
    5
    */
    

    C.路径难题

    Problem

    题目地址

    Solution

    对于每一路的公交车,建立一个虚拟节点,将该路公交车所有站点与虚拟节点相连,跑最短路。

    用一个二元组 ((x,y)) 表示路径长度,其中 (y in [0,r))。把边分为两类,一种乘公交车,一种不乘公交车。乘公交车要将 (y) 清空,如果 (y>0) 那么要将 (x+1) 再加上路径长度。

    Code

    Talk is cheap.Show me the code.

    #include<bits/stdc++.h>
    #define mp make_pair
    #define fi first
    #define se second
    using namespace std;
    inline int read() {
        int x = 0, f = 1; char ch = getchar();
        while(ch<'0' || ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
        while(ch>='0'&&ch<='9') { x=(x<<3)+(x<<1)+(ch^48); ch=getchar(); }
        return x * f;
    }
    typedef pair<int,int> PII;
    const int N = 400007;
    int n,m,cnt,K,r;
    int head[N],c[N];
    struct Edge {
    	int next,to,w,flag;
    }edge[N<<1];
    inline void add(int u,int v,int w,int flag) {
    	edge[++cnt] = (Edge)<%head[u],v,w,flag%>;
    	head[u] = cnt;
    }
    PII dist[N];
    bool vis[N];
    void Dijkstra(int s) {
    	memset(dist, 0x3f, sizeof(dist));
    	memset(vis, 0, sizeof(vis));
    	priority_queue<pair<PII,int> > q;
    	dist[s] = mp(0,0), vis[s] = 0; q.push(mp(dist[s], s));
    	while(!q.empty()) {
    		int u = q.top().se; vis[u] = 1; q.pop();
    		for(int i=head[u];i;i=edge[i].next) {
    			int v = edge[i].to, w = edge[i].w, flag = edge[i].flag;
    			PII now = dist[u];
    			if(flag == 0) {
    				now.se += w;
    				if(now.se >= r) {
    					now.fi += now.se/r, now.se %= r;
    				}
    			} else {
    				if(now.se > 0) now.fi++;
    				now.fi += w; now.se = 0;
    			}
    			//printf("%d->%d (%d,%d)->(%d,%d) %d %d
    ",u,v,dist[u].fi,dist[u].se,now.fi,now.se,w,flag);
    			if(dist[v] > now) {
    				dist[v] = now; 
    				now.fi = -now.fi; now.se = -now.se;
    				q.push(mp(now,v));
    			}
    		}
    	}
    }
    int main()
    {
    	n = read(), m = read(), K = read(), r = read(); int q = read();
    	for(int i=1;i<=m;++i) {
    		int u = read(), v = read(), w = read();
    		add(u,v,w,0), add(v,u,w,0);
    	}
    	int tot = n;
    	for(int i=1;i<=K;++i) {
    		int t = read(); c[i] = read(); ++tot;
    		for(int j=1;j<=t;++j) {
    			int x = read(); add(x,tot,c[i],1), add(tot,x,0,0);
    		}
    	}
    	while(q--) {
    		int x = read(), y = read();
    		Dijkstra(x);
    		PII ans = dist[y];
    		if(ans.se > 0) ans.fi++;
    		printf("%d
    ",ans.fi);
    		//PII now = dist[2];
    		//printf("%d %d
    ",now.fi,now.se);
    	}
        return 0;
    }
    /*
    5 6 1 10 1
    1 2 15
    2 3 177
    3 5 73
    4 2 37
    1 5 66
    1 4 43
    3 11 1 3 5
    1 3
    
    11
    */
    
  • 相关阅读:
    isNUll ,对于sql中的一个表的description的NULL和空格的处理
    Thread类学习
    java学习计划
    HTTP请求过程(http是一种无状态协议,即不建立持久的连接)
    JS事件流(W3C与IE区别)
    学习Javascript闭包
    div内长串数字或字母不断行处理
    仿购物车加减数字
    多行文字两行断尾点点点显示
    MegaCli命令详解
  • 原文地址:https://www.cnblogs.com/BaseAI/p/13900591.html
Copyright © 2020-2023  润新知