zoukankan      html  css  js  c++  java
  • 比赛-OBlack学长的训练赛 (25 Aug, 2018)

    A. 试卷##

    B. 果实##

    据说是另一道题的弱化版,原题带修改,好像需要用 set 维护节点。这题数据非常友善,可以用莫队水过(块长卡了 (n^{frac{1}{2}}) 但没卡 (n^{frac{2}{3}}) )。
    问题可以用 dfn 序转化为求区间不同元素个数。离线做。将询问根据左端点排序,然后维护一个 BIT ,在某个元素第一次出现的位置处 +1 。然后再 getsum 就可以得到答案了。左端点右移时,把 BIT 上当前位置 -1 ,在当前位置元素下一次出现的位置(用类似链式前向星的方法预处理) +1 即可。
    然而考试结束后 OBlack 说在线更好做。树上差分即可。比如某元素的出现的 dfn 值分别为 (1,3,10,20) ,则在这些位置 +1 ;然后在同元素 dfn 值相邻的两个节点的 lca 处 -1 ,即在 (lca_{1,3},lca_{3,10},lca_{10,20}) 处 -1 。之后对于每个询问,求子树权值和即可。

    离线 BIT 做法

    #include <cstdio>
    #include <algorithm>
    #include <ctype.h>
    #include <vector>
    
    using namespace std;
    
    char *p1, *p2, buf[1 << 20], sss[50];
    
    inline char gc()
    {
    	return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))==p1?EOF:*p1++;
    }
    
    template<typename T>
    void rd(T &num)
    {
    	char tt;
    	while (!isdigit(tt = gc()));
    	num = tt - '0';
    	while (isdigit(tt = gc()))
    		num = num * 10 + tt - '0';
    	return;
    }
    
    template<typename T>
    void pt(T num)
    {
    	int top = 0;
    	do sss[++top] = num % 10 + '0';
    	while (num /= 10);
    	while (top)
    		putchar(sss[top--]);
    	putchar('
    ');
    	return;
    }
    
    const int _N = 501000;
    
    vector<int> G[_N];
    int dfn[_N], siz[_N], A[_N], B[_N], bit[_N], nxt[_N], fst[_N], ans[_N];
    int Time, N, M, C;
    
    struct data {
    	int id, v;
    	bool operator < (const data &tmp)
    	const
    	{
    		return dfn[v] < dfn[tmp.v];
    	}
    } Q[_N];
    
    void build(int p, int dad)
    {
    	dfn[p] = ++Time, siz[p] = 1, B[dfn[p]] = A[p];
    	for (int i = G[p].size() - 1; i >= 0; --i) {
    		int v = G[p][i];
    		if (v != dad)
    			build(v, p), siz[p] += siz[v];
    	}
    	return;
    }
    
    void add(int k, int d)
    {
    	for (int i = k; i <= N; i += i & -i)
    		bit[i] += d;
    	return;
    }
    
    int getsum(int k)
    {
    	int sum = 0;
    	for (int i = k; i; i ^= i & -i)
    		sum += bit[i];
    	return sum;
    }
    
    int main()
    {
    	
    	rd(N), rd(M), rd(C);
    	for (int i = 1; i <= N; ++i)
    		rd(A[i]);
    	for (int a, b, i = 1; i < N; ++i) {
    		rd(a), rd(b);
    		G[a].push_back(b), G[b].push_back(a);
    	}
    	build(1, 0);
    	for (int i = N; i >= 1; --i)
    		nxt[i] = fst[B[i]], fst[B[i]] = i;
    	for (int i = 1; i <= N; ++i)
    		if (fst[B[i]] == i)
    			add(i, 1);
    	for (int t, i = 1; i <= M; ++i)
    		rd(Q[i].v), Q[i].id = i;
    	sort(Q + 1, Q + 1 + M);
    	int pos = 1;
    	for (int i = 1; i <= M; ++i) {
    		while (pos < dfn[Q[i].v]) {
    			add(pos, -1);
    			if (nxt[pos]) add(nxt[pos], 1);
    			++pos;
    		}
    		ans[Q[i].id] = getsum(dfn[Q[i].v] + siz[Q[i].v] - 1);
    	}
    	for (int i = 1; i <= M; ++i)
    		pt(ans[i]);
    	return 0;
    }
    

    C. 旅行##

    #include <cstdio>
    #include <algorithm>
    #include <ctype.h>
    #include <vector>
    #include <queue>
    
    using namespace std;
    
    char *p1, *p2, buf[1 << 20], sss[50];
    
    inline char gc()
    {
    	return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))==p1?EOF:*p1++;
    }
    
    template<typename T>
    void rd(T &num)
    {
    	char tt;
    	while (!isdigit(tt = gc()));
    	num = tt - '0';
    	while (isdigit(tt = gc()))
    		num = num * 10 + tt - '0';
    	return;
    }
    
    template<typename T>
    void pt(T num)
    {
    	int top = 0;
    	do sss[++top] = num % 10 + '0';
    	while (num /= 10);
    	while (top)
    		putchar(sss[top--]);
    	putchar('
    ');
    	return;
    }
    
    const int _N = 51000;
    
    struct edge {
    	int v, w;
    	edge(int v = 0, int w = 0):
    		v(v), w(w) { }
    	bool operator < (const edge &tmp)
    	const
    	{
    		return w > tmp.w;
    	}
    };
    
    priority_queue<edge> Q;
    vector<edge> G[_N];
    int dis[_N];
    int N, M, ans = -1;
    
    int dijkstra(int lim, int t)
    {
    	for (int i = 0; i <= N; ++i)
    		dis[i] = -1;
    	dis[1] = 0, Q.push(edge(1, 0));
    	while (!Q.empty()) {
    		edge p = Q.top();
    		Q.pop();
    		if (p.w != dis[p.v]) continue;
    		for (int i = G[p.v].size() - 1; i >= 0; --i) {
    			edge v = G[p.v][i];
    			
    			if (p.v == 1 && v.v >> lim & 1 ^ t) continue;
    			if (v.v == 0 && p.v >> lim & 1 ^ t ^ 1) continue;
    			
    			if (dis[v.v] == -1 || dis[v.v] > dis[p.v] + v.w)
    				Q.push(edge(v.v, dis[v.v] = dis[p.v] + v.w));
    		}
    	}
    	return dis[0];
    }
    
    int main()
    {
    	rd(N), rd(M);
    	for (int x, y, c, d, i = 1; i <= M; ++i) {
    		rd(x), rd(y), rd(c), rd(d);
    		if (x > y) swap(x, y), swap(c, d);
    		G[x].push_back(edge(y, c));
    		if (x == 1) x = 0;
    		G[y].push_back(edge(x, d));
    	}
    	int tmp = ,N cnt = 0;
    	while (tmp) ++cnt, tmp >>= 1;
    	for (int i = 0; i < cnt; ++i) {
    		int t = dijkstra(i, 0);
    		if (t != -1 && (ans == -1 || ans > t)) ans = t;
    		t = dijkstra(i, 1);
    		if (t != -1 && (ans == -1 || ans > t)) ans = t;
    	}
    	pt(ans);
    	return 0;
    }
    
  • 相关阅读:
    1091 Acute Stroke
    1092 To Buy or Not to Buy
    1093 Count PAT's
    1094 The Largest Generation
    1095 Cars on Campus
    1096 Consecutive Factors
    1097 Deduplication on a Linked List
    2.掌握Python基本数据类型,从python陌路人到熟人!
    Python基础语法,他其实很贵!
    某外企软件测试面试题整理(更新中)
  • 原文地址:https://www.cnblogs.com/ghcred/p/9534742.html
Copyright © 2011-2022 走看看