zoukankan      html  css  js  c++  java
  • 2020.02.01【NOIP提高组】模拟A 组 总结

    啊啊啊,开局不利啊。。。

    估分:(50 + 30 + 0 = 80)
    考场:(20 + 0 + 0 = 20)

    (T1)

    一开始想了个贪心,手玩了几个数据后就证萎了。
    然后开始思考(DP),首先(O(n^2)DP)很容易想到。
    (f[i][j])表示一个以(i)结尾,另一个以(j)结尾的最小值。另(i>j)
    发现当(j!=i-1)时,一定从(f[i-1][j])转移,否则从(f[j][k])转移。(n^2)枚举。
    第一维可以开滚动。然后就(50)分了。(作死又改成伪贪心,只有(20)了)
    发现转移是:前面一坨都加一个固定的值,(i-1)位则是在前面的(min)中加一个值。
    然后想到线段树。但发现那个值是不固定的,然后就弃疗了。

    (solution)

    我们发现对于每个答案(f[n][i])都可以看成(f[i][i-1]+sum[n]-sum[i])
    所以其实我们只需要求出每个(f[i][i-1])即可(设(g[i])表示(f[i][i-1])
    方程式:(g[i]=min(g[j]+sum[i-1]-sum[j]+|h[i]-h[j-1]|))
    由于有(abs),我们可以开两个线段树。一个表示(h[i]>=h[j-1])时的值,另一个相反。
    然后我们只需要维护线段树即可。操作简单方便。

    (T2)

    一开始没有什么想法。
    后来(3min)打了个(30)分,结果细节打错了。。。
    正解回过头来想想看,发现其实也是有一定的可想性的。
    我们发现(n)很小,但是边数很大,所以一定有很多的重边。
    所以我们可以从重边依照(k1,k2)来比较大小从而发现一定的规律。(式子自己推一推)
    然后我们可以将(u)排序,然后发现只有凸包上的顶点才是有用的。
    所以我们可以将没有用的删掉。然后在按照(k1/k2)来选点,我们发现最近(k1/k2)的且大于它的更优(当(u1>u2))时。
    所以我们只需要将询问按照(k1/k2)排一边序,然后对于两两点之间选的边就一定是不断往后的了。我们可以用(prim)来求答案。
    代码的常数巨大,请小心驾驶。

    (code)

    #include <cstdio>
    #include <vector>
    #include <algorithm>
    #define N 200010
    #define db double
    #define fo(x, a, b) for (register int x = (a); x <= (b); x++)
    #define fd(x, a, b) for (register int x = (a); x >= (b); x--)
    using namespace std;
    struct xw{db k1, k2; int fr;}ask[N];
    int n, m, Q, point[37][37], num[37][37];
    pair<int, int> b[N];
    vector<pair<int, int> > edge[37][37];
    db ans = 0, aw[N], eg[37][37];
    
    inline int read()
    {
    	int x = 0, f = 0; char c = getchar();
    	while (c < '0' || c > '9') f = (c == '-') ? 1 : f, c = getchar();
    	while (c >= '0' && c <= '9') x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
    	return f ? -x : x;
    }
    
    inline bool cmp(pair<int, int> x, pair<int, int> y) {return x.first == y.first ? x.second < y.second : x.second > y.second;;}
    
    inline bool cmp1(xw x, xw y) {return x.k1 * y.k2 < y.k1 * x.k2;}
    
    inline bool cmp_first(pair<int, int> x, pair<int, int> y) {return x.first == y.first ? x.second > y.second : x.first > y.first;}
    
    inline db calc(pair<int, int> x, pair<int, int> y) {return (db)(y.second - x.second) / (x.first - y.first);}
    
    db prim()
    {
    	db ans = 0.0;
    	static db d[37];
    	static bool tag[37];
    	tag[1] = 1, d[1] = 0;
    	fo(i, 2, n) d[i] = eg[1][i], tag[i] = 0;
    	fo(i, 2, n)
    	{
    		int k = 0;
    		fo(j, 1, n)
    			if (! tag[j] && (! k || d[j] < d[k])) k = j;
    		if (! k) continue;
    		tag[k] = 1, ans += d[k];
    		fo(j, 1, n)
    			if (! tag[j]) d[j] = min(d[j], eg[j][k]);
    	}
    	return ans;
    }
    
    int main()
    {
    	n = read(), m = read(), Q = read();
    	fo(i, 1, m)
    	{
    		int x = read(), y = read(), u = read(), v = read();
    		if (x < y) edge[x][y].push_back(make_pair(u, v));
    		else edge[y][x].push_back(make_pair(u, v));
    	}
    	fo(i, 1, n)
    		fo(j, i + 1, n)
    		{
    			int len = edge[i][j].size(), len1 = -1;
    			fo(k, 0, len - 1) b[k + 1] = edge[i][j][k];
    			std::sort(b + 1, b + len + 1, cmp_first);
    			edge[i][j].clear();
    			fo(k, 1, len)
    			{
    				while (len1 >= 0 && (b[k].second <= edge[i][j][len1].second || (len1 >= 1 && calc(edge[i][j][len1], edge[i][j][len1 - 1]) > calc(b[k], edge[i][j][len1]))))
    					edge[i][j].pop_back(), len1--;
    				edge[i][j].push_back(b[k]), len1++;
    			}
    			num[i][j] = len1;
    		}
    	fo(i, 1, Q) scanf("%lf%lf", &ask[i].k1, &ask[i].k2), ask[i].fr = i;
    	std::sort(ask + 1, ask + Q + 1, cmp1);
    	fo(k, 1, Q)
    	{
    		fo(i, 1, n)
    			fo(j, i + 1, n)
    			{
    				while (point[i][j] < num[i][j] && ask[k].k1 > calc(edge[i][j][point[i][j]], edge[i][j][point[i][j] + 1]) * ask[k].k2) point[i][j]++;
    				if (point[i][j] <= num[i][j])
    					eg[i][j] = eg[j][i] = edge[i][j][point[i][j]].first * ask[k].k1 + edge[i][j][point[i][j]].second * ask[k].k2;
    				else eg[i][j] = eg[j][i] = 1e16;
    			}
    		aw[ask[k].fr] = prim();
    	}
    	fo(i, 1, Q) printf("%.3lf
    ", aw[i]);
    	return 0;
    }
    

    (T3)

    完全没有什么想法。
    题解也没有清楚理解。

    总结

    要给自己留足时间去打码。
    贪心一定要先证一证,万一证萎了呢?
    想题是一步步来的,不要一上来就刚正解。

    转载需注明出处。
  • 相关阅读:
    子网掩码
    子网
    ARP
    IPv6
    Host-Only(仅主机模式)
    NAT(地址转换模式)
    Bridged(桥接模式)
    VMware配置网络/Linux
    three months timestamp
    spring cloud禁止输出日志:ConfigClusterResolver : Resolving eureka endpoints via configuration
  • 原文地址:https://www.cnblogs.com/jz929/p/12249285.html
Copyright © 2011-2022 走看看