LOJ3146 APIO2019路灯(cdq分治+树状数组)

  每个时刻都形成若干段满足段内任意两点可达。将其视为若干正方形。则查询相当于求历史上某点被正方形包含的时刻数量。并且注意到每个时刻只有O(1)个正方形出现或消失,那么求出每个矩形的出现时间和消失时间,就是裸的三维偏序,cdq分治+树状数组即可。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 1000000010
#define N 300010
#define mp(x,y) make_pair((x),(y))
#define fi first
#define se second
#define time se.fi
#define ans se.se
#define val se.se
#define left fi.fi
#define right fi.se
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
	int x=0,f=1;char c=getchar();
	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
	while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
	return x*f;
}
typedef pair<int,int> pii;
typedef pair<pii,pii> ppp;
int n,m,t,u,v,a[N],tree[N];
char s[N];
set<ppp> seg;
ppp b[N<<1],q[N];
pii o;
struct data
{
	ppp x;int op;
	bool operator <(const data&a) const
	{
		return x.time<a.x.time||x.time==a.x.time&&x.fi<a.x.fi||x.time==a.x.time&&x.fi==a.x.fi&&op<a.op;
	}
}c[N*3],d[N*3];
void add(int k,int x){while (k<=n) tree[k]+=x,k+=k&-k;}
int query(int k){int s=0;while (k) s+=tree[k],k-=k&-k;return s;}
void solve(int l,int r)
{
	if (l==r) return;
	int mid=l+r>>1;
	solve(l,mid);
	solve(mid+1,r);
	int cur=l-1;
	for (int i=mid+1;i<=r;i++)
	if (c[i].op==1)
	{
		while (cur<mid&&(c[cur+1].op==1||c[cur+1].x.left<=c[i].x.left))
		{
			cur++;
			if (c[cur].op==0) add(c[cur].x.right,c[cur].x.val);
		}
		c[i].x.ans+=query(c[i].x.right);
	}
	for (;cur>=l;cur--) if (c[cur].op==0) add(c[cur].x.right,-c[cur].x.val);
	int i=l,j=mid+1;
	for (int k=l;k<=r;k++)
	if (i<=mid&&(j>r||c[i].x.left<c[j].x.left)) d[k]=c[i++];else d[k]=c[j++];
	for (int k=l;k<=r;k++) c[k]=d[k];
}
signed main()
{
#ifndef ONLINE_JUDGE
	freopen("a.in","r",stdin);
	freopen("a.out","w",stdout);
#endif
	n=read(),m=read();
	scanf("%s",s+1);
	for (int i=1;i<=n;i++) a[i]=s[i]-'0';
	if (!a[1]) seg.insert(mp(o,o));
	for (int i=1;i<=n;i++)
	if (a[i])
	{
		int t=i;
		while (t<n&&a[t+1]==1) t++;
		seg.insert(mp(mp(i-1,t),o));
		i=t;
	}
	else if (!a[i+1]) seg.insert(mp(mp(i,i),o));
	for (int i=1;i<=m;i++)
	{
		/*for (auto it=seg.begin();it!=seg.end();it++)
		cout<<(*it).left<<' '<<(*it).right<<' '<<(*it).time<<endl;
		cout<<endl;*/
		char c=getc();
		if (c=='q')
		{
			int l=read()-1,r=read()-1;
			q[++t]=mp(mp(l,r),mp(i-1,0));
			auto it=seg.upper_bound(mp(mp(l,n+1),o));
			if (it!=seg.begin())
			{
				it--;
				if ((*it).right>=r) q[t].ans=i-(*it).time;
			}
		}
		else
		{
			int x=read();
			if (a[x])
			{
				auto it=seg.lower_bound(mp(mp(x,0),o));it--;
				ppp tmp=*it;seg.erase(it);
				b[++u]=mp(tmp.fi,mp(i-1,i-tmp.time));
				seg.insert(mp(mp(tmp.left,x-1),mp(i,0)));
				seg.insert(mp(mp(x,tmp.right),mp(i,0)));
			}
			else
			{
				auto it=seg.lower_bound(mp(mp(x,0),o));
				auto it2=it;it2--;
				ppp tmp=*it;seg.erase(it);
				ppp tmp2=*it2;seg.erase(it2);
				b[++u]=mp(tmp.fi,mp(i-1,i-tmp.time));
				b[++u]=mp(tmp2.fi,mp(i-1,i-tmp2.time));
				seg.insert(mp(mp(tmp2.left,tmp.right),mp(i,0)));
			}
			a[x]^=1;
		}
	}
	n++;
	for (int i=1;i<=t;i++) q[i].right=n-q[i].right;
	for (int i=1;i<=u;i++) b[i].right=n-b[i].right;
	/*for (int i=1;i<=t;i++) cout<<q[i].left<<' '<<q[i].right<<' '<<q[i].time<<' '<<q[i].ans<<endl;
	cout<<endl;
	for (int i=1;i<=u;i++) cout<<b[i].left<<' '<<b[i].right<<' '<<b[i].time<<' '<<b[i].val<<endl;*/
	//求left<=q[i].left right<=q[i].right time<=q[i].time 的权值和
	/*for (int i=1;i<=t;i++)
		for (int j=1;j<=u;j++)
		if (b[j].left<=q[i].left&&b[j].right<=q[i].right&&b[j].time<=q[i].time) q[i].ans+=b[j].val;*/
	for (int i=1;i<=t;i++) c[++v].x=q[i],c[v].op=1;
	for (int i=1;i<=u;i++) c[++v].x=b[i],c[v].op=0;
	sort(c+1,c+v+1);
	solve(1,v);
	sort(c+1,c+v+1);
	for (int i=1;i<=v;i++) if (c[i].op==1) printf("%d\n",c[i].x.ans);
	return 0;
	//NOTICE LONG LONG!!!!!
}

  

posted @ 2019-07-08 15:24  Gloid  阅读(...)  评论(...编辑  收藏