zoukankan      html  css  js  c++  java
  • 2020.1.2考试总结

    T1圆圈游戏
    暴力DP有60分,设包含圆i的最小的圆是fa[i],那没最终会的得到一棵树,对于一棵子树,选了根节点就不能选子树内其它点,f[i]=max(w[i],(sum f[son])).
    瓶颈就在怎么建图,因为圆不相交相切,所以扫描线的时候相对位置不会发生改变,用set维护一下就好啦。

    #include<algorithm>
    #include<iostream>
    #include<cmath>
    #include<queue>
    #include<cstdio>
    #include<set>
    using namespace std;
    int n, ans, tmp, lx;
    const int N = 200010;
    int f[N], fa[N];
    struct yuan 
    {
    	int x, y, r, w;
    	double h(int dir) {return y + dir * sqrt(1.0 * r * r - (1.0 * lx - x) * (lx - x));}
    } y[N];
    struct hu 
    {
    	int dir, id;
    	friend bool operator <(const hu &a, const hu &b)
    	{return a.id == b.id ? a.dir < b.dir : (y[a.id].h(a.dir) < y[b.id].h(b.dir));}
    } b[N];
    inline int read() 
    {
    	int res = 0; char ch = getchar(); bool XX = false;
    	for (; !isdigit(ch); ch = getchar())(ch == '-') && (XX = true);
    	for (; isdigit(ch); ch = getchar())res = (res << 3) + (res << 1) + (ch ^ 48);
    	return XX ? -res : res;
    }
    int my(hu a, hu b) {return y[a.id].x - a.dir * y[a.id].r < y[b.id].x - a.dir * y[b.id].r;}
    set<hu>s;
    set<hu>::iterator it;
    signed main() 
    {
    	cin >> n;
    	for (int i = 1; i <= n; ++i) 
    	{
    		y[i].x = read(); y[i].y = read(); y[i].r = read(); y[i].w = read();
    		b[++tmp] = (hu) {1, i}, b[++tmp] = (hu) { -1, i};
    	}
    	sort(b + 1, b + 1 + tmp, my);
    	for (int i = 1; i <= tmp; ++i) 
    	{
    		int id = b[i].id, dir = b[i].dir;
    		lx = y[id].x - dir * y[id].r;
    		if (dir == 1) 
    		{
    			if (!s.empty()) 
    			{
    				it = s.upper_bound(b[i]);
    				if (it != s.end())
    					fa[id] = (it->dir == 1) ? it->id : fa[it->id];
    			}
    			s.insert((hu) {1, id}); s.insert((hu) { -1, id});
    		} else 
    		{
    			s.erase((hu) {1, id}); s.erase((hu) { -1, id});
    			f[fa[id]] += max(f[id], y[id].w);
    		}
    	}
    	cout << f[0];
    	return 0;
    }
    

    T2划分序列
    很明显的二分答案,关键就在于check。
    设f1[i]表示在i处划分一下,在满足mid的条件下最少划分次数,f2[i]表示最多的划分次数,若(f1[n] le k le f2[n])则mid合法。
    暴力dp是(O(n^2))的,发现更新f1,f2的是区间最大/最小值,用树状数组维护一下就可以了。

    #include<algorithm>
    #include<iostream>
    #include<cstdio>
    #include<map>
    using namespace std;
    int n, k, ans, tot;
    const int N = 100010, inf = 1 << 30;
    int a[N], f1[N], f2[N], tr1[N], tr2[N], b[N], t1[N], t2[N];
    inline int read() 
    {
    	int res = 0; char ch = getchar(); bool XX = false;
    	for (; !isdigit(ch); ch = getchar())(ch == '-') && (XX = true);
    	for (; isdigit(ch); ch = getchar())res = (res << 3) + (res << 1) + (ch ^ 48);
    	return XX ? -res : res;
    }
    inline int lowbit(int x) {return x & (-x);}
    void change1(int pos, int val) 
    {
    	for (; pos; pos -= lowbit(pos))tr1[pos] = min(tr1[pos], val);
    }
    int ask1(int pos) 
    {
    	int res = inf;
    	for (; pos <= tot; pos += lowbit(pos))res = min(res, tr1[pos]);
    	return res;
    }
    void change2(int pos, int val) 
    {
    	for (; pos; pos -= lowbit(pos))tr2[pos] = max(tr2[pos], val);
    }
    int ask2(int pos) 
    {
    	int res = -inf;
    	for (; pos <= tot; pos += lowbit(pos))res = max(res, tr2[pos]);
    	return res;
    }
    int check2(int mid) 
    {
    	tot = 0;
    	for (int i = 0; i <= n; ++i) 
    	{
    		b[++tot] = a[i];
    		b[++tot] = a[i] - mid;
    	}
    	sort(b + 1, b + 1 + tot);
    	tot = unique(b + 1, b + 1 + tot) - b - 1;
    	for (int i = 0; i <= n; ++i) 
    	{
    		t1[i] = lower_bound(b + 1, b + 1 + tot, a[i]) - b;
    		t2[i] = lower_bound(b + 1, b + 1 + tot, a[i] - mid) - b;
    	}
    	for (int i = 1; i <= tot; ++i)tr1[i] = inf, tr2[i] = -inf;
    	change1(t1[0], 0); change2(t1[0], 0);
    	for (int i = 1; i <= n; ++i) 
    	{
    		f1[i] = ask1(t2[i]) + 1; f2[i] = ask2(t2[i]) + 1;
    		change1(t1[i], f1[i]); change2(t1[i], f2[i]);
    	}
    	return f1[n] <= k && k <= f2[n];
    }
    void solve2() 
    {
    	int l = 0, r = 0;
    	for (int i = 1; i <= n; ++i)
    		if (a[i] < 0)l += a[i];
    		else r += a[i];
    	for (int i = 1; i <= n; ++i)a[i] += a[i - 1];
    	while (l <= r) 
    	{
    		int mid = (l + r) / 2;
    		if (check2(mid))ans = mid, r = mid - 1;
    		else l = mid + 1;
    	}
    	cout << ans;
    }
    int main() 
    {
    	cin >> n >> k;
    	for (int i = 1; i <= n; ++i)a[i] = read();
    	solve2();
    	return 0;
    }
    

    T3生成树求和
    由于加法不进位,所以每一位我们单独考虑。
    用矩阵树定理求的是(sum)所有生成树边权的积,而这里我们需要求的是边权和,所以三次单位根的乘法来完成加法。
    最后还要求解一下三元一次方程,可以选择高斯消元,也可以像我一样手动消元。

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #define int long long
    #define LL long long
    using namespace std;
    int n, m, ans;
    const LL N = 105, mod = 1e9 + 7, inv2 = (mod + 1) >> 1, inv3 = (mod + 1) / 3, sqrt3 = 82062379;
    int fr[N * N], to[N * N], val[N * N], bin[20];
    inline int read() 
    {
    	int res = 0; char ch = getchar(); bool XX = false;
    	for (; !isdigit(ch); ch = getchar())(ch == '-') && (XX = true);
    	for (; isdigit(ch); ch = getchar())res = (res << 3) + (res << 1) + (ch ^ 48);
    	return XX ? -res : res;
    }
    LL ksm(LL a, LL b, LL mod) 
    {
    	LL res = 1;
    	for (; b; b >>= 1, a = a * a % mod)
    		if (b & 1)res = res * a % mod;
    	return res;
    }
    struct xu 
    {
    	LL a, b;
    	xu(int _a = 0, int _b = 0) {a = _a, b = _b;}
    	friend xu operator +(const xu &x, const xu &y)
    	{return (xu) {(x.a + y.a) % mod, (x.b + y.b) % mod};}
    	friend xu operator -(const xu &x, const xu &y)
    	{return (xu) {(x.a - y.a + mod) % mod, (x.b - y.b + mod) % mod};}
    	friend xu operator *(const xu &x, const xu &y)
    	{return (xu) {(x.a * y.a % mod - x.b * y.b % mod + mod) % mod, (x.a * y.b + x.b * y.a) % mod};}
    	friend xu operator *(const xu &x, const int &y)
    	{return (xu) {(x.a * y) % mod, (x.b * y) % mod};}
    	friend xu operator /(const xu &x, const int &y) 
    	{
    		int inv = ksm(y, mod - 2, mod);
    		return (xu) {(x.a * inv) % mod, (x.b * inv) % mod};
    	}
    	friend xu operator /(const xu &x, const xu &y) 
    	{
    		return x * (xu) {y.a, mod - y.b} / ((y.a * y.a % mod + y.b * y.b % mod) % mod);
    	}
    } w[3], invw[3], a[N][N], coef[3], inv;
    xu work() 
    {
    	xu res = xu(1, 0);
    	for (int i = 1; i < n; ++i) 
    	{
    		for (int j = i; j < n; ++j)
    			if (a[j][i].a || a[j][i].b) 
    			{
    				if (i == j)break;
    				swap(a[i], a[j]); res = res * (mod - 1);
    				break;
    			}
    		for (int j = i + 1; j < n; ++j) 
    		{
    			inv = a[j][i] / a[i][i];
    			for (int k = i; k < n; ++k)a[j][k] = a[j][k] - inv * a[i][k];
    		}
    		res = res * a[i][i];
    	}
    	return res;
    }
    void solve(xu *p) 
    {
    	xu tmp[3];
    	tmp[0] = p[0]; tmp[1] = p[1]; tmp[2] = p[2];
    	p[0] = tmp[0] + tmp[1] + tmp[2];
    	p[1] = tmp[0] + tmp[1] * invw[1] + tmp[2] * invw[2];
    	p[2] = tmp[0] + tmp[1] * invw[2] + tmp[2] * invw[1];
    	for (int i = 0; i <= 2; ++i)p[i] = p[i] * inv3;
    }
    LL suan(int p) 
    {
    	int k;
    	xu w0, w1, w2, c;
    	for (int i = 0; i <= 2; ++i) 
    	{
    		memset(a, 0, sizeof(a));
    		w0 = xu(1, 0); w1 = w[i]; w2 = w[(i + i) % 3];
    		for (int j = 1; j <= m; ++j) 
    		{
    			k = val[j] / bin[p] % 3;
    			c = (k == 1 ? w1 : (k == 2 ? w2 : w0));
    			a[fr[j]][fr[j]] = a[fr[j]][fr[j]] + c;
    			a[to[j]][to[j]] = a[to[j]][to[j]] + c;
    			a[fr[j]][to[j]] = a[fr[j]][to[j]] - c;
    			a[to[j]][fr[j]] = a[to[j]][fr[j]] - c;
    		}
    		coef[i] = work();
    	}
    	solve(coef);
    	return ((coef[1].a + coef[2].a + coef[2].a) % mod) * bin[p] % mod;
    }
    signed main() 
    {
    	freopen("sum.in", "r", stdin);
    	freopen("sum.out", "w", stdout);
    	cin >> n >> m;
    	w[0] = xu(1, 0); w[1] = xu(mod - inv2, sqrt3 * inv2 % mod);
    	w[2] = xu(mod - inv2, mod - sqrt3 * inv2 % mod);
    	invw[0] = xu(1, 0) / w[0]; invw[1] = xu(1, 0) / w[1]; invw[2] = xu(1, 0) / w[2];
    	for (int i = 1; i <= m; ++i)fr[i] = read(), to[i] = read(), val[i] = read();
    	bin[0] = 1;
    	for (int i = 1; i <= 10; ++i)bin[i] = bin[i - 1] * 3;
    	for (int i = 0; i <= 10; ++i)(ans += suan(i)) %= mod;
    	cout << ans;
    	return 0;
    }
    
  • 相关阅读:
    python json.dumps() json.dump()的区别
    geopy 在python中的使用
    socket技术详解(看清socket编程)
    数据结构之各种数据结构插入、删除、查找的时间复杂度
    数组查找的时间复杂度正确表述
    各种排序算法时间复杂度
    MySQL将一张表的某些列数据,复制到另外一张表,并且修改某些内容
    Java虚拟机学习
    Java虚拟机学习
    java集合框架05——ArrayList和LinkedList的区别
  • 原文地址:https://www.cnblogs.com/wljss/p/12142187.html
Copyright © 2011-2022 走看看