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;
    }
    
  • 相关阅读:
    js中的字符串
    JSOP
    jq总结1
    jq总结
    诗和远方-志
    诗和远方-感
    js判断变量是否为空字符串、null、undefined
    判断js对象是否为空
    诗和远方-悟
    深复制
  • 原文地址:https://www.cnblogs.com/cxhscst2/p/7465136.html
Copyright © 2011-2022 走看看