zoukankan      html  css  js  c++  java
  • luogu2253 好一个一中腰鼓!

    先说一个小trick,一开始我们把他赋值成是红、白相间的,查询就查询的是全红或全白即可。

    然后就可以做啦

    题解里面好像都是线段树

    暴力的题解好像都被del了

    貌似暴力交上去也过不了了

    然后我想说

    分块大法好!

    把同学们他分成(lfloorsqrt N floor)

    每块维护八个信息:

    左边连续白长度,右边连续白长度,块内连续白长度,是否全白,

    左边连续红长度,右边连续红长度,块内连续红长度,是否全红,

    记录两个不变的信息:

    id(废话),块的长度

    每次更新,找到那个同学在哪个块,整块全部暴力更新,根号N
    怎么更新,整个快全扫一遍,统计白的数量和红的数量能把是否全白全红做了,中途统计当前连续白红数量能把最长块内连续长度做了
    然后从块左端往右扫,右端往左扫,把左右两端的长度高了

    每次查询,也是(sqrt N),乱搞搞
    怎么搞,先枚举两种颜色,然后枚举所有区块,更新一个当前能延伸的长度,如果这个区块全是一种颜色就+=(可以连上),否则就直接等于他右端的长度,具体看代码

    复杂度大概(O(Msqrt N))

    由于我经常用调试输出,所以我就没有删除调试输出

    #include <cstdio>
    #include <iostream>
    #include <cmath>
    
    using namespace std;
    
    int n, m, size;
    int a[20010], id[20010];
    int len[200], l[200], r[200];
    struct info
    {
    	bool all;
    	int l, r, x;
    }b[200][2];
    
    int query();
    
    void print()
    {
    	printf("输出调试信息
    ");
    	for (int i = 1; i <= n; i++)
    		printf("%d%c", a[i], i == n ? '
    ' : ' '); 
    	for (int i = 1; i <= id[n]; i++)
    	{
    		printf("第%d块 (%d, %d)", i, l[i], r[i]); 
    		for(int t = 0; t <= 1; t++)
    			printf("[%d %d %d %d]%c", b[i][t].all, b[i][t].l, b[i][t].x, b[i][t].r, t?'
    ':' '); 
    	}
    	printf("当前答案%d
    ", query()); 
    }
    
    //更新区块x 
    void update(int x)
    {
    //	printf("更新了区块%d
    ", x); 
    	int t[2] = {0, 0}, f[2] = {0, 0};
    	b[x][0].x = b[x][1].x = 0;
    	for (int i = l[x]; i <= r[x]; i++)
    	{
    		t[a[i]]++;
    		f[a[i]]++;
    		if(a[i] != a[i - 1])
    		{
    			b[x][a[i - 1]].x = max(b[x][a[i - 1]].x, f[a[i - 1]]);
    			f[a[i - 1]] = 0;
    		}
    	}
    	b[x][a[r[x]]].x = max(b[x][a[n]].x, f[a[r[x]]]);
    	b[x][0].all = (t[0] == len[x]);
    	b[x][1].all = (t[1] == len[x]);
    	b[x][a[l[x]]].l = 1;
    	b[x][a[l[x]] ^ 1].l = 0;
    	b[x][a[r[x]]].r = 1;
    	b[x][a[r[x]] ^ 1].r = 0;
    	for (int i = l[x] + 1; a[i] == a[i - 1] && i <= r[x]; i++)
    		b[x][a[l[x]]].l++;
    	for (int i = r[x] - 1; a[i] == a[i + 1] && i >= l[x]; i--)
    		b[x][a[r[x]]].r++;
    }
    
    //查询当前状态的最大值
    int query()
    {
    	int maxlength[2] = {0, 0}, nowlength[2] = {0, 0}; 
    	for (int t = 0; t <= 1; t++)
    	{
    		for (int i = 1; i <= id[n]; i++)//枚举所有区块 
    		{
    			maxlength[t] = max(maxlength[t], b[i][t].l + nowlength[t]);
    			maxlength[t] = max(maxlength[t], b[i][t].x);
    			if(b[i][t].all == 1)
    				nowlength[t] += len[i];
    			else
    				nowlength[t] = b[i][t].r;
    		}
    		maxlength[t] = max(maxlength[t], nowlength[t]);
    	}
    	return max(maxlength[0], maxlength[1]);
    }
    
    int main()
    {
    	scanf("%d%d", &n, &m);
    	for (int i = 1; i <= n; i++)
    		a[i] = (i & 1);
    	size = sqrt(n);
    	for (int i = 1; i <= n; i++)
    	{
    		id[i] = (i - 1) / size + 1;
    		len[id[i]]++;
    		if ((i - 1) % size == 0)
    			l[id[i]] = i;
    		if (i % size == 0)
    			r[id[i]] = i;
    	}
    	r[id[n]] = n;
    	for (int i = 1; i <= id[n]; i++)
    		update(i);
    //	print();
    	for (int x, i = 1; i <= m; i++)
    	{
    		scanf("%d", &x);
    		a[x] ^= 1;
    		update(id[x]);
    //		print();
    		printf("%d
    ", query());
    	}
    	return 0;
    }
    

    瞎扯几句

    据说写分快是对出题人的不尊重??但是这题难度标签对我不尊重2333。。。

    一个线段树模板就是绿题了,这题黄题 显然不用线段树能过,所以我就写了分块

    经验/启示:以后懒得写线段树但是又比较勤快可以试试分块

  • 相关阅读:
    2017-2018 20155309南皓芯 信息安全系统基础设计第十三周博客
    2017-2018-1 20155309 《信息安全系统设计基础》实验五 通信协议设计
    20155309南皓芯《信息安全系统设计基础》实验四:外设驱动设备设计 实验报告
    2017-2018 20155309 南皓芯 信息安全基础设计第十一周博客
    2017-2018 20155309 南皓芯 信息安全基础设计第十周博客
    2017-2018 20155309南皓芯实验三实时系统
    linux pwd指令C实现
    2017-2018 20155309 南皓芯 信息安全基础设计第九周博客
    2017-2018-1 20155304 《信息安全系统设计基础》第十四周学习总结
    20155304 《信息安全系统设计基础》第十三周学习总结
  • 原文地址:https://www.cnblogs.com/oier/p/9596652.html
Copyright © 2011-2022 走看看