codeforces 461C 暴力+BIT

        題意是這點線段,每次兩種操作,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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章