zoukankan      html  css  js  c++  java
  • 2017 ACM/ICPC 广西邀请赛 题解

    题目链接  Problems

    HDOJ上的题目顺序可能和现场比赛的题目顺序不一样,

    我这里的是按照HDOJ的题目顺序来写的。

    Problem 1001

    签到

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define rep(i, a, b)	for (int i(a); i <= (b); ++i)
    
    typedef long long LL;
    
    LL n, f[31];
    int ans;
    
    
    int main(){
    
    	f[1] = 1LL;
    	for (LL i = 2; i <= 15; ++i){
    		f[i] = 1LL;
    		rep(j, 1, i) f[i] *= i;
    	}
    
    	while (~scanf("%lld", &n)){
    		ans = 0;
    		rep(i, 1, 15) if (f[i] <= n) ans = max(ans, i);
    		printf("%d
    ", ans);
    	}	
    
    
    	return 0;
    }
    

    Problem 1002

    这道题的话,其实一个点上是可以有多种颜色的

    因为最多只有51种颜色,所以我们维护51棵线段树即可。

    我们对y坐标建立线段树,对于每个y,我们只需要知道最小的x在哪里即可。

    因为他的询问的x坐标下界总是1,那么我们只要看看y1到y2的最小值是否小于等于给定的x即可。

    询问的时候做51次子询问就可以了。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define rep(i, a, b)	for (int i(a); i <= (b); ++i)
    #define dec(i, a, b)	for (int i(a); i >= (b); --i)
    
    typedef long long LL;
    
    const int N = 2e6 + 10;
    
    int X, c, d, x, y, op, ans, ret, cnt;
    int root[53];
    int l[N], r[N], v[N];
    
    void update(int &i, int L, int R, int x, int val){
    	if (i == 0){
    		i = ++cnt;
    		v[i] = val;
    	}
    
    	v[i] = min(v[i], val);
    	if (L == R) return;
    
    	int mid = (L + R) >> 1;
    	if (x <= mid) update(l[i], L, mid, x, val);
    	else update(r[i], mid + 1, R, x, val);
    }
    
    void query(int i, int L, int R){
    	if (ret || i == 0) return;
    	if (c <= L && R <= d){
    		if (v[i] <= X) ret = 1;
    		return;
    	}
    
    	int mid = (L + R) >> 1;
    	if (c <= mid) query(l[i], L, mid);
    	if (d >  mid) query(r[i], mid + 1, R);
    }	
    
    int main(){
    
    	while (true){
    		scanf("%d", &op);
    		if (op == 3) break;
    		if (op == 0){
    			rep(i, 1, cnt) l[i] = r[i] = 0;
    			memset(root, 0, sizeof root);
    			cnt = 0;
    		}
    
    		if (op == 1){
    			scanf("%d%d%d", &x, &y, &c);
    			update(root[c], 1, 1000000, y, x);
    		}
    
    		if (op == 2){
    			scanf("%d%d%d", &X, &c, &d);
    			ans = 0;
    			rep(i, 0, 50){
    				ret = 0;
    				query(root[i], 1, 1000000);
    				ans += ret;
    			}
    			printf("%d
    ", ans);
    		}
    	}
    
    
    	return 0;
    }
    

    Problem 1003

    我们对于每一条边,找到所有包含这条边的三元环,个数计为x

    然后这对答案的贡献就是$C_{x}^{2}$

    判断两点之间是否有边的时候要手写哈希才能过

    #include <bits/stdc++.h>
    
    const int N = 2e5 + 10;
    
    #define rep(i, a, b)	for (int i(a); i <= (b); ++i)
    #define dec(i, a, b)	for (int i(a); i >= (b); --i)
    
    namespace Hashmap{
    	const int P = 1000007, seed = 2333;
    	int u[N << 2], v[N << 2], nt[N << 2];
    	int head[P], inum;
    	inline void init(){
    		inum = 0;
    		memset(u, 0, sizeof u);
    		memset(v, 0, sizeof v);
    		memset(nt, 0, sizeof nt);
    		memset(head, 0, sizeof head);
    	}
    
    	inline void add(int _u, int _v){
    		int t = (_u * seed + _v) % P;
    		u[++inum] = _u, v[inum] = _v, nt[inum] = head[t], head[t] = inum;
    	}
    
    	inline bool query(int _u, int _v){
    		int t = (_u * seed + _v) % P;
    		for (int p = head[t]; p; p = nt[p])
    			if (u[p] == _u && v[p] == _v) return 1;
    		return 0;
    	}
    }
    
    using namespace std;
    using namespace Hashmap;
    
    typedef long long LL;
    
    vector<int> a[N];
    
    struct ss{ int x, y; } e[N];
    
    int n, m;
    
    int main(){
    
    	while (~scanf("%d%d",&n, &m)){
    		init();
    		rep(i, 1, n) a[i].clear();
    		rep(i, 1, m){
    			int x, y;
    			scanf("%d%d", &x, &y);
    			e[i].x = x;
    			e[i].y = y;
    			a[x].push_back(y);
    			a[y].push_back(x);
    			add(x, y);
    			add(y, x);
    		}
    
    		LL ans = 0;
    		rep(i, 1, m){
    			int x = e[i].x, y = e[i].y;
    			if (a[e[i].y].size() < a[e[i].x].size()) swap(x, y);
    			LL tot = 0;
    			for (auto u: a[x]) if (query(u, y))  tot++;
    			ans += tot * (tot - 1) / 2;
    		}
    
    		printf("%lld
    ", ans);
    	}
    	return 0;
    }
    

    Problem 1004

    这题规律找了半天……

    $f[n] = f[n - 1] + 5f[n - 2] + f[n - 3] - f[n - 4]$

    然后矩阵加速下就可以了

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define rep(i, a, b)	for (int i(a); i <= (b); ++i)
    #define dec(i, a, b)	for (int i(a); i >= (b); --i)
    #define MP		make_pair
    #define fi		first
    #define se		second
    
    
    typedef long long LL;
    
    const LL mod = 1e9 + 7;
    
    struct Matrix{
    	LL arr[6][6];
    } f, unit, a;
    
    
    LL m, k;
    int n;
    
    Matrix Add(Matrix a, Matrix b){
    	Matrix c;
    	rep(i, 1, n) rep(j, 1, n){
    		c.arr[i][j] = (a.arr[i][j] + b.arr[i][j]) % mod;
    	}
    	return c;
    }
    
    Matrix Mul(Matrix a, Matrix b){
    	Matrix c;
    	rep(i, 1, n) rep(j, 1, n){
    		c.arr[i][j] = 0;
    		rep(k, 1, n) (c.arr[i][j] += (a.arr[i][k] * b.arr[k][j] % mod)) %= mod;
    	}
    	return c;
    }
    
    Matrix Pow(Matrix a, LL k){
    	Matrix ret(unit); for (; k; k >>= 1, a = Mul(a, a)) if (k & 1) ret = Mul(ret, a); return ret;
    }
    
    
    int main(){
    
    	n = 4;
    
    	memset(f.arr, 0, sizeof f.arr);
    	memset(a.arr, 0, sizeof a.arr);
    	memset(unit.arr, 0, sizeof unit.arr);
    
    	rep(i, 1, n) unit.arr[i][i] = 1;
    	f.arr[1][1] = 1;
    	f.arr[1][2] = 5;
    	f.arr[1][3] = 1;
    	f.arr[1][4] = 1000000006;
    	f.arr[2][1] = 1;
    	f.arr[3][2] = 1;
    	f.arr[4][3] = 1;
    	
    	a.arr[1][1] = 36;
    	a.arr[2][1] = 11;
    	a.arr[3][1] = 5;
    	a.arr[4][1] = 1;
    
    	while (~scanf("%lld", &m)){
    		if (m == 1LL){ puts("1");  continue;}
    		if (m == 2LL){ puts("5");  continue;}
    		if (m == 3LL){ puts("11"); continue;}
    		if (m == 4LL){ puts("36"); continue;}
    		if (m == 5LL){ puts("95"); continue;}
    
    		k = m - 4;
    
    		Matrix b = Pow(f, k);
    		Matrix c = Mul(b, a);
    		printf("%lld
    ", c.arr[1][1]);		
    	}
    
    	return 0;
    }
    

    Problem 1010

    这道题的话先转DFS序,然后求出以每个点为根的子树的对应区间,

    于是就转化成了求区间里选一个数和x异或后的最大值。

    可持久化trie即可。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    
    #define rep(i, a, b)	for (int i(a); i <= (b); ++i)
    #define dec(i, a, b)	for (int i(a); i >= (b); --i)
    
    
    typedef long long LL;
    
    const int N = 1e5 + 10;
    const int M = 1e7 + 10;
    
    int n, m, tot = 0;
    int rt[N], id[M], t[M][2];
    int l, r, x;
    int a[N], c[N], L[N], R[N], g[N];
    int ti;
    int u;
    
    
    vector <int> v[N];
    
    
    inline void insert(int pre, int x, int k){
    
    	int now = rt[k] = ++tot; id[tot] = k;
    
    	dec(i, 30, 0){
    		int j = (x >> i) & 1;
    		t[now][j ^ 1] = t[pre][j ^ 1];
    		t[now][j] = ++tot;
    		id[tot] = k;
    		now = t[now][j];
    		pre = t[pre][j];
    	}
    }
    
    
    inline int query(int l, int r, int x){
    
    	int ans = 0, tmp = rt[r];
    
    	dec(i, 30, 0){
    		if (id[tmp] < l) break;
    		int j = ((x >> i) & 1) ^ 1;
    		if (id[t[tmp][j]] >= l) ans |= (1 << i);
    		else j ^= 1;
    		tmp = t[tmp][j];
    	}
    
    	return ans;
    }
    
    void dfs(int x){
    	L[x]  = ++ti;
    	g[ti] = a[x];
    	for (auto u : v[x]){
    		dfs(u);
    	}
    	R[x] = ti;
    }
    
    
    int main(){
    
    	while (~scanf("%d%d", &n, &m)){
    		memset(id, 0, sizeof id);
    		memset(rt, 0, sizeof rt);
    		memset(t, 0, sizeof t);
    		memset(L, 0, sizeof L);
    		memset(R, 0, sizeof R);
    
    		tot = 0;
    		ti = 0;
    
    		rep(i, 0, n + 1) v[i].clear();
    		rep(i, 1, n) scanf("%d", a + i);
    		rep(i, 2, n){
    			scanf("%d", &x);
    			v[x].push_back(i);
    		}
    
    		dfs(1);
    
    		id[0] = -1;
    		insert(0, 0, 0);
    		
    		rep(i, 1, n) insert(rt[i - 1], g[i], i);
    
    		rep(i, 1, m){
    			scanf("%d%d", &u, &x);
    			printf("%d
    ", query(L[u], R[u], x));
    		}
    
    	}
    	return 0;
    }
    
  • 相关阅读:
    智能推荐算法演变及学习笔记(三):CTR预估模型综述
    从中国农业银行“雅典娜杯”数据挖掘大赛看金融行业数据分析与建模方法
    智能推荐算法演变及学习笔记(二):基于图模型的智能推荐(含知识图谱/图神经网络)
    (设计模式专题3)模板方法模式
    (设计模式专题2)策略模式
    (设计模式专题1)为什么要使用设计模式?
    关于macOS上常用操作命令(持续更新)
    记录下关于RabbitMQ常用知识点(持续更新)
    EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT. RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE.
    SpringCloud教程二:Ribbon(Finchley版)
  • 原文地址:https://www.cnblogs.com/cxhscst2/p/7465136.html
Copyright © 2011-2022 走看看