zoukankan      html  css  js  c++  java
  • NOI.ac模拟赛20181021 ball sequence color

    T1 ball

    可以发现每次推动球时,是将每个球的位置 1-1 ,然后把最左边的球放到 P1P-1 处。

    记个 1-1 次数,再用set维护就好了。

    #include <bits/stdc++.h>
    using namespace std;
    int n, q, p, now;
    set<int>ball;
    
    inline void read(int &num)
    {
    	char ch; num = 0; int flag = 1;
    	while((ch=getchar()) < '0' || ch > '9')if(ch == '-') flag = -flag;
    	while(ch >= '0' && ch <= '9') num = num*10 + ch-'0', ch = getchar();
    	num *= flag;
    }
    
    int main()
    {
    	int x, y;
    	read(n), read(q), read(p);
    	for(int i = 1; i <= n; i++)
    		read(x), ball.insert(x);
    	for(int i = 1; i <= q; i++)
    	{
    		read(x);
    		if(x == 1)
    			read(y), ball.insert(y+now);
    		else
    			ball.erase(ball.begin()), ball.insert(p+(now++));
    	}
    	set<int>::iterator it;
    	bool flag = 0;
    	for(it = ball.begin(); it != ball.end(); it++)
    	{
    		if(!flag) flag = 1;
    		else putchar(' ');
    		printf("%d", (*it)-now);
    	}
    }
    

    T2 sequence

    f(i,a,b,c)f(i, a, b, c) 表示考虑前 ii 个,换进了 aa 个,换出了 bb 个,当前的位置是 c(0/1/2)c(0/1/2) 的答案。其中 00 是在选择的区间之前, 11 是在选择的区间之中, 22 是之后。每次 O(1)O(1) 讨论一下当前位置的数的情况。

    #include <bits/stdc++.h>
    using namespace std;
    #define LL long long
    const int MAXN = 100001;
    const int MAXK = 11;
    int n, k, v[MAXN];
    LL f[2][MAXK][MAXK][3];
    short pre[MAXN][MAXK][MAXK][3];
    inline void Max(int now, int i, int a, int b, int c, int lasta, int lastb, int val, int flag)
    {
    	for(int lastc = max(c-1, 0); lastc <= c; lastc++)
    		if(f[now^1][lasta][lastb][lastc] + val > f[now][a][b][c])
    			f[now][a][b][c] = f[now^1][lasta][lastb][lastc] + val, pre[i][a][b][c] = flag * 10 + lastc;
    }
    int in[MAXN], cur_in;
    int out[MAXN], cur_out;
    int d[2], cur_d;
    inline void Getans(int i, int a, int b, int c)
    {
    	if(!i) return;
    	int A = a, B = b, C = pre[i][a][b][c] % 10, flag = pre[i][a][b][c] / 10;
    	if(flag == 2) A--, in[++cur_in] = i;
    	if(flag == 3) B--, out[++cur_out] = i;
    	if(i == n && c == 1) d[cur_d++] = i;
    	if(c == 2 && C == 1) d[cur_d++] = i-1;
    	if(c == 1 && C == 0) d[cur_d++] = i;
    	Getans(i-1, A, B, C);
    }
    int main ()
    {
    	memset(pre, -1, sizeof pre);
    	scanf("%d%d", &n, &k);
    	for(int i = 1; i <= n; i++) scanf("%d", &v[i]);
    	int now = 0;
    	memset(f[now], -0x3f, sizeof f[now]);
    	f[now][0][0][0] = 0;
    	for(int i = 1; i <= n; i++)
    	{
    		now ^= 1;
    		memset(f[now], -0x3f, sizeof f[now]);
    		for(int a = 0; a <= k; a++)
    			for(int b = 0; b <= k; b++)
    			{
    				Max(now, i, a, b, 0, a, b, 0, 1); //1
    				if(a)Max(now, i, a, b, 0, a-1, b, v[i], 2); //2
    				Max(now, i, a, b, 1, a, b, v[i], 1); //1
    				if(b)Max(now, i, a, b, 1, a, b-1, 0, 3); //3
    				Max(now, i, a, b, 2, a, b, 0, 1); //1
    				if(a)Max(now, i, a, b, 2, a-1, b, v[i], 2); //2
    			}
    	}
    	int X = -1, Y;
    	for(int x = 0; x <= k; x++)
    		for(int y = 1; y < 3; y++)
    			if(X == -1 || f[now][X][X][Y] < f[now][x][x][y])
    				X = x, Y = y;
    	Getans(n, X, X, Y);
    	printf("%lld %d
    ", f[now][X][X][Y], X);
    	for(int i = 1; i <= cur_in; i++)
    		printf("%d %d
    ", in[i], out[i]);
    	printf("%d %d
    ", min(d[0], d[1]), max(d[0], d[1]));
    }
    

    T3 color

    方法一

    考虑一个叶子节点到根的路径上的点的颜色,那么一定是前面一段的颜色与叶子节点的颜色相同,然后剩下一段的颜色均为灰色。那么每次修改就先减去原来路径上的颜色然后再加上修改后路径上的颜色,每个颜色的个数可以直接二分求出两种颜色的相交处即可。

    一个节点为黑色或白色当且仅当以它为根的子树中的所有叶子节点颜色相同。那么可以求出一个DFS序,然后直接用线段树来维护,叶子节点颜色。

    总复杂度:O(nlogn2)O(n*logn^2)

    方法二

    求两种颜色的相交处,可以是求最近的一个灰色的节点,那么一定是这个叶子节点与另一种颜色节点的深度最深的LCA。这个必然是和它在DFS序最相近的两个点,可以用set维护每种颜色的叶子节点的DFS序值,直接查询然后倍增求LCA即可。

    总复杂度:O(nlogn)O(n*logn)

    方法三、四(水过)

    1.缩链,把只有一个son的father缩成一个点暴力处理,水过
    2.直接暴力,每次向上跑,修改颜色&答案,如果修改过后的颜色与原来颜色一样就停止
    PS:很水(miao)的数据,卡大暴力去了

    #include <bits/stdc++.h>
    using namespace std;
    #define LL long long
    namespace IO
    {
    	template<class T>inline void read(T &num)
    	{
    		char ch; int flag = 1;
    		while(!isdigit(ch=getchar()))if(ch=='-')flag=-flag;
    		for(num=ch-'0';isdigit(ch=getchar());num=num*10+ch-'0');
    		num *= flag;
    	}
    }
    using namespace IO;
    
    const int MAXN = 100005;
    
    struct node
    {
    	int u, v, wt;
    	friend bool operator <(node x, node y)
    	{ return x.wt < y.wt; }
    }e[MAXN];
    int n, c[MAXN], sz[MAXN], fa[MAXN];
    LL total, sum[MAXN];
    
    inline int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); }
    
    bool check(int mid)
    {
    	for(int i = 1; i <= n; i++) fa[i] = i, sum[i] = sz[i] = 0;
    	for(int i = 1; i < mid; i++) fa[find(e[i].v)] = find(e[i].u);
    	for(int i = 1; i <= n; i++) sum[find(i)] += c[i], sz[find(i)]++;
    	for(int i = 1; i <= n; i++) if(fa[i] == i && total-sum[i] < sz[i]) return 0;
    	return 1;
    }
    
    int main ()
    {
    	//freopen("shuju.in", "r", stdin);
    	read(n);
    	for(int i = 1; i < n; i++)
    		read(e[i].u), read(e[i].v), read(e[i].wt);
    	sort(e + 1, e + n);
    	for(int i = 1; i <= n; i++)
    		read(c[i]), total += c[i];
    	int l = 1, r = n-1, mid;
    	while(l < r)
    	{
    		mid = (l + r + 1) >> 1;
    		if(check(mid)) l = mid;
    		else r = mid-1;
    	}
    	printf("%d
    ", e[l].wt);
    }
    
  • 相关阅读:
    Win7专业版系统下事件绑定的Command事件不执行
    Win8系统下报错:无法将字符串“*”转换为Length.
    C#创建job计划用于调用存储过程刷新数据
    with语句
    for in语句与for in语句输入顺序问题
    HighCharts日期及数值格式化
    在web.config文件中,增加“type="APP.Modules.CommandModule,CommandModules"”节点会导致awesome font字体图标显示为方框框
    String、StringBuffer与StringBuilder之间区别
    java使用maven创建springmvc web项目
    手机APP下单支付序列图
  • 原文地址:https://www.cnblogs.com/Orz-IE/p/12039505.html
Copyright © 2011-2022 走看看