• 【vijos】1881 闪烁的繁星(线段树+特殊的技巧)


    https://vijos.org/p/1881

    这场比赛太难了sad。所以我都没做。。

    这题一开始我竟然不会sad(本来就不会),然后我继续yy。。yy了好久,竟然yy了个什么可拆分的并查集?(sad,后来发现我是如此sb,根本无法实现。。)

    然后我弃疗了,比赛干脆不交了。。sad

    后来看了题解和神犇们热心的指导,这就是一水题。。

    sad。

    我们只需要在线段树维护三个值,L表示这个节点的区间内从左边向又能延伸的最长可行串的长度,R表示这个节点的区间内从右边向左能延伸的最长可行串的长度,mx表示这个区间最长的可行串的长度。

    那么我们在pushup里面只需要这样转移即可

    void pushup(int x, int len) {
    	int l=lc, r=rc;
    	t[x].x=t[l].x; 
    	t[x].y=t[r].y;
    	t[x].lx=t[l].lx;
    	t[x].rx=t[r].rx;
    	t[x].mx=max(t[l].mx, t[r].mx);
    	if(t[l].y!=t[r].x) {
    		t[x].mx=max(t[x].mx, t[l].rx+t[r].lx);
    		if(t[l].mx==(len-(len>>1))) t[x].lx=max(t[x].lx, t[l].mx+t[r].lx);
    		if(t[r].mx==(len>>1)) t[x].rx=max(t[x].rx, t[r].mx+t[l].rx);
    	}
    }
    

    这个多想想就知道为什么了。。。(因为我是蒟蒻所以我想不出来。orz

    然后这题就成为水题了。

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <string>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    using namespace std;
    #define rep(i, n) for(int i=0; i<(n); ++i)
    #define for1(i,a,n) for(int i=(a);i<=(n);++i)
    #define for2(i,a,n) for(int i=(a);i<(n);++i)
    #define for3(i,a,n) for(int i=(a);i>=(n);--i)
    #define for4(i,a,n) for(int i=(a);i>(n);--i)
    #define CC(i,a) memset(i,a,sizeof(i))
    #define read(a) a=getint()
    #define print(a) printf("%d", a)
    #define dbg(x) cout << (#x) << " = " << (x) << endl
    #define printarr2(a, b, c) for1(_, 1, b) { for1(__, 1, c) cout << a[_][__]; cout << endl; }
    #define printarr1(a, b) for1(_, 1, b) cout << a[_] << '	'; cout << endl
    inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; }
    inline const int max(const int &a, const int &b) { return a>b?a:b; }
    inline const int min(const int &a, const int &b) { return a<b?a:b; }
    const int N=200005;
    #define lc x<<1
    #define rc x<<1|1
    #define lson l, m, lc
    #define rson m+1, r, rc
    #define MID (l+r)>>1
    
    struct dat { int lx, rx, x, y, mx; }t[N<<2];
    int n, Q;
    void pushup(int x, int len) {
    	int l=lc, r=rc;
    	t[x].x=t[l].x; 
    	t[x].y=t[r].y;
    	t[x].lx=t[l].lx;
    	t[x].rx=t[r].rx;
    	t[x].mx=max(t[l].mx, t[r].mx);
    	if(t[l].y!=t[r].x) {
    		t[x].mx=max(t[x].mx, t[l].rx+t[r].lx);
    		if(t[l].mx==(len-(len>>1))) t[x].lx=max(t[x].lx, t[l].mx+t[r].lx);
    		if(t[r].mx==(len>>1)) t[x].rx=max(t[x].rx, t[r].mx+t[l].rx);
    	}
    }
    void build(int l, int r, int x) {
    	t[x].mx=t[x].x=t[x].y=t[x].lx=t[x].rx=1;
    	if(l==r) return;
    	int m=MID;
    	build(lson); build(rson);
    }
    void upd(int l, int r, int x, int p) {
    	if(l==r) { t[x].x=t[x].y=!t[x].x; return; }
    	int m=MID;
    	if(p<=m) upd(lson, p); else upd(rson, p);
    	pushup(x, r-l+1);
    }
    int main() {
    	read(n); read(Q);
    	build(1, n, 1);
    	while(Q--) {
    		upd(1, n, 1, getint());
    		printf("%d
    ", t[1].mx);
    	}
    	return 0;
    }
    

    背景

    繁星闪烁着--深蓝的太空
    何曾听得见他们对语
    沉默中
    微光里
    他们深深的互相颂赞了

    描述

    繁星, 漫天的繁星.
    繁星排成一列, 我数一数呀, 一共有N只小星星呢.

    星星们是听话的好孩子, 小岛在指挥它们跳舞呢.
    舞蹈开始前, 它们都亮了起来!

    小岛指一指第i只小星星, 只见第i只小星星立刻改变了自己的状态.
    如果它之前是亮着的, 那么立刻就灭掉了.
    如果它之前是灭掉的, 现在就立刻亮了呀!

    如果说, 可以有连续若干只小星星.
    其中任意相邻两只星星状态不同.
    那就是最美的了.

    小岛希望知道:
    每一次发出指令之后
    能找到最长的连续小星星, 满足上述需求的
    有多长?

    格式

    输入格式

    第一行有两个整数, 分别为星星总数N, 和指令总数Q.
    1<=N<=200,000; 1<=Q<=200,000.
    之后Q行, 每行有一个整数i: 1<=i<=N, 表示小岛发出的指令.

    输出格式

    输出有Q行, 其中每i行有一个整数.
    表示小岛的第i条指令发出之后, 可以找到的满足要求的最长连续星星序列有多长?

    样例1

    样例输入1[复制]

    6 2
    2
    4

    样例输出1[复制]

    3
    5

    限制

    对于20%的数据: N, Q <= 100.
    对于30%的数据: N, Q <= 70000.
    对于100%的数据: 1 <= N, Q <= 200,000.

    提示

    对于样例, 星星序列的状态依次为: OOOOOO -> OXOOOO -> OXOXOO
    这里用O表示亮着的星星, 用X表示灭掉的星星.

  • 相关阅读:
    c++ readIntger writeIntger
    c++ string split function
    uniapp 创建简单的tabs
    c++ 获取和设置 窗口标题
    两种js数组去重的方法
    将jquery和公共样式缓存到localStorage,可以减少Http请求,从而优化页面加载时间
    H5 多个视频 循环播放效果
    使用iScroll时,input等不能输入内容的解决方法
    修改EsayUi 中 tree 的原有样式,变为according 之类的样式 ,且子菜单显示在右侧
    跨浏览器的事件对象-------EventUtil 中的方法及用法
  • 原文地址:https://www.cnblogs.com/iwtwiioi/p/4008223.html
Copyright © 2020-2023  润新知