codeforces 461C 暴力+BIT

本文探讨了一个涉及线段折叠和区间查询的问题,通过使用树状数组或线段树来解决单点更新和区间求和的需求。重点介绍了下表维护和坐标转换的技巧,以及如何通过翻转和区间更新来处理不同情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        题意是这点线段,每次两种操作,1 x表示把线段以x作为新的起点折叠,2 x y表示查询[x,y]这个区间有几条单位线段..详情参考原题给出样例解释...首先给每个线段编号,a[i]表示[i,i+1]这段有几个单位线段,那么每次折叠的时候,如果x左侧长度小于等于x右侧长度,则直接把x左边的每一个数加到对应的位置上,否则就相当于把右侧的每一个数加到对应的左侧位置上,并且将整个区间翻转。查询就是查一下a[x]--a[y-1]的区间和,考虑每次1操作,暴力循环每个位置相加,那么就成了一个单点更新,区间查询的问题,树状数组或者线段树都可以解决,当然树状数组常数上会有些优势。这题最恶心的就是下表的维护...用l,r记录一下当前区间的左端右端,rev记录区间是否被翻转过,每次1先由给出的相对l的坐标算出绝对坐标,然后循环更新,最后按需要修改l,r,rev的值,查询即直接算出绝对坐标求和....最近智商感觉下线了...推坐标转换推了好久......

/*=============================================================================
#  Author:Erich
#  FileName:
=============================================================================*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <map>
#include <queue>
#include <stack>
#define lson id<<1,l,m
#define rson id<<1|1,m+1,r

using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const ll INF=1ll<<60;
const double PI=acos(-1.0);
const int maxn=100500;
int n,m;
int l,r;
int a[maxn];
inline int lowbit(int x)
{
	return x&(-x);
}
void add(int x,int c)
{
	for (int i=x; i<=n; i+=lowbit(i))
		a[i]+=c;
}
int sum(int x)
{
	if (!x) return 0;
	int res=0;
	for (int i=x; i>0; i-=lowbit(i))
		res+=a[i];
	return res;
}
void print()
{
    for (int i=l; i<=r; i++)
    cout<<sum(i)-sum(i-1)<<" ";
    cout<<endl;
}
int main()
{
//	freopen("in.txt","r",stdin);
	while(~scanf("%d%d",&n,&m))
	{
	    int nn=n;
		memset(a,0,sizeof a);
		for (int i=1; i<=n; i++)  add(i,1);
		int cmd,x,y;
		bool rev=false;
		l=1;
		r=n;
		//print();
		for (int i=0; i<m; i++)
		{
			int j,k;
			scanf("%d",&cmd);
			if (cmd==1)
			{
				scanf("%d",&x);
				x++;
				if (rev)
				{
					x=r+1-x+1;
					if (x-l>r-x+1)
					{
						for(j=x-1,k=x;k<=r;j--,k++)
						{
							add(j,sum(k)-sum(k-1));
						}
						r=x-1;
					}
					else
					{
						for (j=x,k=x-1;k>=l;j++,k--)
						{
							add(j,sum(k)-sum(k-1));
						}
						l=x;
						rev^=1;
					}
				}
				else
				{
					x+=l-1;
					if (x-l>r-x+1)
					{
						for (j=x-1,k=x; k<=r;j--,k++)
						{
							add(j,sum(k)-sum(k-1));
						}
						rev^=1;
						r=x-1;
					}
					else
					{
						for (j=x,k=x-1;k>=l;j++,k--)
						{
							add(j,sum(k)-sum(k-1));
						}
						l=x;
					}
				}
				//print();
				nn=r-l+1;
			}
			else
			{
				scanf("%d%d",&x,&y);
				x++;
				y++;
				int ans=0;
				if (rev)
				{
					x=r+1-x+1;
					y=r-y+1;
					cout<<sum(x-1)-sum(y)<<endl;
				}
				else
				{
					x+=l-1;
					y+=l-1;
					cout<<sum(y-1)-sum(x-1)<<endl;
				}

			}
		}
	}

	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值