首页 > 其他分享 >P7110 晚秋绝诗 题解

P7110 晚秋绝诗 题解

时间:2023-12-01 15:14:36浏览次数:43  
标签:q1 P7110 q2 int 题解 绝诗 op it2 it1

好有意思的题目啊。

出题人太厉害了。

思路

考虑一个结论:

我们将两个没插旗的点与中间的点称为一段,其中中间的点必须全部插旗。

那么这一段如果已知两座山的高度,就一定可以得知所有的高度。

考虑为什么。

加入这一段是 \(a\sim b\)。

\[\begin{cases} h_a+h_{a+2}=2\times h_{a+1}\\ h_{a+1}+h_{a+3}=2\times h_{a+2}\\ h_{a+2}+h_{a+4}=2\times h_{a+3}\\ h_{a+3}+h_{a+5}=2\times h_{a+4}\\ \cdots\\ h_{b-2}+h_{b}=2\times h_{b-1}\\ \end{cases} \]

总共可以列出 \(b-a-1\) 个方程。

而这一段总共只有 \(b-a+1\) 个未知量。

所以只需要知道其中两个即可。

这启发我们将整个序列按照是否插旗分段。

例如一个序列:

0110000111010

其中 \(0\) 表示没插旗,\(1\) 表示插旗。

所以整个序列可以分为如下几段。

\((1,4),(4,5),(5,6),(6,7),(7,11),(11,13)\)。

每个端点既是一个区间的左端点又是一个区间的右端点(除了最左和最右)。

很明显,端点属于极其特殊的点。

假如一个区间的所有点可以被求出,那么这个端点就相当于一个传递一样的给了别的区间。

那么我们只需要对于一个区间找到它两边的区间的端点是否能传递给他即可。

这可以让我们进行一个分类。

  1. 一个区间内有两个以上已知点,那么这是非常好的,整个区间也都知道了。
  2. 一个区间内有一个已知点且不是端点,那么发现这种段是起到了一个传递的作用,也就是只要另一边可以传递过来,那么它也可以传递出去,所以可知这种段有没有都无所谓。
  3. 其余的所有区间都可以归为一类,只需要判断相应的端点是否有雾即可。

这里感觉比其它题解少分了一类,简化了很多。

分完类,就有了一些很好的做法了。

我们使用两个 \(\text{set}\)。

一个维护连续段,一个维护第一类和第三类来查端点。

再使用线段树或树状数组维护区间已知点数量。

我采用了线段树。

代码也很好写。

Code

\(\text{2.23KiB}\)。

相较于其他的题解应该算很短的。

#include<bits/stdc++.h>
using namespace std;

#define fro(i,x,y) for(int i=(x);i<=(y);i++)
#define pre(i,x,y) for(int i=(x);i>=(y);i--)

const int N=5e5+10;

int n,m,x,op,a[N],b[N],t[N*4];
struct Node{
	int l; mutable int r,op;
	bool operator<(const Node&tmp)const
		{ return l<tmp.l; }
};
set<Node> q1,q2;

#define mid ((l+r)>>1)
void upd(int p,int l,int r,int v,int k){
	if(l==r)return t[p]=k,void();
	if(mid>=v)upd(p*2,l,mid,v,k);
	else upd(p*2+1,mid+1,r,v,k);
	t[p]=t[p*2]+t[p*2+1];
}
int ask(int p,int l,int r,int ls,int rs){
	if(ls<=l&&r<=rs)return t[p];int sum{};
	if(mid>=ls)sum+=ask(p*2,l,mid,ls,rs);
	if(mid<rs)sum+=ask(p*2+1,mid+1,r,ls,rs);
	return sum;
}
void upd(Node tmp){
	auto it1=q1.lower_bound(tmp);
	auto it2=q2.lower_bound(tmp);
	int s=ask(1,1,n,it1->l,it1->r);
	it1->op=(s>=2?1:((a[it1->l]||a[it1->r]||!s)?2:3));
	if(it1->op!=3){
		if(it1->l!=it2->l)
			q2.insert(*it1);
		else it2->op=it1->op;
	}
	else if(it1->l==it2->l)
		q2.erase(it2);
}
bool check(Node tmp){
	int s=ask(1,1,n,tmp.l,tmp.r);
	auto it1=q2.upper_bound(tmp);
	auto it2=prev(q2.lower_bound(tmp));
	if(it1!=q2.end()&&!a[tmp.r]&&(a[it1->l]||it1->op==1))s++;
	if(it2->l<tmp.l&&!a[tmp.l]&&(a[it2->r]||it2->op==1))s++;
	return s>=2;
}
void upd1(int x){
	a[x]^=1,upd(1,1,n,x,a[x]);
	auto it=q1.lower_bound({x,0,0});
	if(x!=n&&!b[x])upd(*it);
	if(it!=q1.begin())upd(*prev(it));
}
void ins(int x){
	auto it2=q1.lower_bound({x,0,0});
	auto it1=prev(it2);
	if(it1->op!=3)q2.erase(*it1);
	if(it2->op!=3)q2.erase(*it2);
	it1->r=it2->r,q1.erase(*it2);
	upd(*it1);
}
void del(int x){
	auto it=prev(q1.lower_bound({x,0,0}));
	if(it->op!=3)q2.erase(*it);
	int l=it->l,r=it->r; q1.erase(it);
	auto it1=q1.insert({l,x,0}).first;
	auto it2=q1.insert({x,r,0}).first;
	upd(*it1),upd(*it2);
}
void upd2(int x){b[x]^=1,(b[x]==1?ins(x):del(x));}
int ask(int x){
	bool flag=0;
	if(a[x]==1)return 1;
	auto it=q1.lower_bound({x,0,0});
	if(x!=n&&b[x]==0)flag|=check(*it);
	if(it!=q1.begin())flag|=check(*prev(it));
	return flag;
}
int main(){
	ios::sync_with_stdio(0),cin.tie(0);
	cin>>n>>m;
	fro(i,1,n-1)
		q1.insert({i,i+1,4}),
		q2.insert({i,i+1,4});
	fro(i,1,m){
		cin>>op>>x;
		if(op==1)upd1(x);
		if(op==2)upd2(x);
		if(op==3)
			cout.rdbuf()->sputc((ask(x)?'1':'0')),
			cout.rdbuf()->sputc('\n');
	}
	return 0;
}

标签:q1,P7110,q2,int,题解,绝诗,op,it2,it1
From: https://www.cnblogs.com/mfeitveer/p/17869723.html

相关文章

  • Advent of Code 2023题解 [Mathematica/Python]
    Day1Part1(*读取文件*)lines=ReadList["E:\\ExplorerDownload\input.txt",String];(*计算校准值*)calibrationValues=ToExpression[StringJoin[#[[1]],#[[-1]]]]&/@(StringCases[#,DigitCharacter]&/@lines);(*打印总和*)Pri......
  • CF1198题解
    CF1198CodeforcesRound576(Div.1)CF1198AlinkCF1198A题意有一种数字化一段录音的常用方式,是记录每一个时刻的强度值。这些非负的强度值就可以代表一段音频对于一段音频,若有\(K\)个不同的强度值,那么每一位我们都需要\(k=\lceil\log_2K\rceil\)\(\text{bit}\)来存......
  • [AGC052B] Tree Edges XOR 题解
    题目链接点击打开链接题目解法怎么感觉这场\(B\)比\(C\)思维量更大考虑一步很妙的操作:把边权变成点权,以达到简化操作的目的使每条边的边权为两端点的异或和,手画一下可以发现,操作简化成了交换两端点的点权我们定义\(d_{1/2,i}\)定义为在\(1/2\)树上,\(i\)到根的权值......
  • CF1684题解
    CF1684CodeforcesRound792(Div.1+Div.2)CF1684AlinkCF1684A题意有一个用十进制表示的没有前导零的正整数\(n\)。Alice和Bob正在用这个数玩一个游戏。Alice先手,他们轮流进行游戏。在她的这一轮中,Alice应该交换这个数中的任何不同位置的两位。轮到Bob时,他每次......
  • [AGC052C] Nondivisible Prefix Sums 题解
    题目链接点击打开链接题目解法好题!一个序列是不合法的,必定满足某些结论,我们不妨猜测一下首先如果和为\(P\)的倍数,必定不合法然后手玩几个可以发现,最极限的情况是\(P-1\)个\(1\;+\;\)\(b_i\;+\;\)\(P-b_i\)如果在这个情况下再加一个\(1\),就爆了其中\(1\)可以替......
  • CF689题解
    CF689CodeforcesRound361(Div.2)CF689AlinkCF689A题意题目描述迈克在海滩游泳时不小心将手机放入水中。他买了一个带有老式键盘的手机。键盘只有十个数字大小的键,位于以下方式:1234567890联系人与他的旧手机一起消失了,他现在只能记住他的手指......
  • 商家转账到零钱全攻略:开通、使用、区别与常见问题解答
    一、商家转账到零钱功能介绍微信作为中国最受欢迎的社交平台之一,其支付功能也相当强大。其中,商家转账到零钱功能可以让商家直接将款项转入用户的微信零钱,方便快捷。本文将详细介绍商家转账到零钱的功能、开通条件、使用方法以及常见问题解答。二、商家转账到零钱场景说明商家转......
  • axios(ajax)发送请求响应码200,但获取不到数据,无法加载响应数据: No datafound for res
    问题截图:没有响应数据控制台报错其实是由于浏览器的跨域资源共享(CORS)策略导致,前后端跨域请求是不行的。什么是域,看页面的url,比如https://www.baidu.com/下的网页都是属于baidu.com这个域。如果你是和我一样是从本地文件打开html的方式来调试ajax,那么一定会出现这个问题,因为本......
  • CF1846E2 Rudolf and Snowflakes (hard version) 题解
    题意:\(T\)\((\)\(1\)\(\le\)\(T\)\(\le\)\(10^4\)\()\)组询问:是否存在一个满\(k\)(\(k\)\(\ge\)\(2\)\()\)叉树节点数恰好为\(n\)\((\)\(1\)\(\le\)\(n\)\(\le\)\(10^{18}\)\()\),且深度\(depth\)至少为\(2\)。思路:满$k$......
  • luogu2839题解
    [国家集训队]middle题目分析代码如下。#include<bits/stdc++.h>usingnamespacestd;typedeflonglongll;typedefunsignedlonglongull;constintMAXN=2e4+10;intx,n,Q,a[MAXN],q[6],root[MAXN],b[MAXN],tot;vector<int>locp[MAXN];structSegmentTreeNode{......