zoukankan      html  css  js  c++  java
  • 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
    ",c[i].x.ans);
    	return 0;
    	//NOTICE LONG LONG!!!!!
    }
    

      

  • 相关阅读:
    Web API总结
    @Html.Raw() 方法输出带有html标签的字符串
    jQuery
    图与树基础-完全图的判定
    图和树基础-蒜头君旅行
    PAT乙级1008
    PAT乙级1007
    PAT乙级1005
    PAT乙级1001
    前端工程化-webpack简介(一)
  • 原文地址:https://www.cnblogs.com/Gloid/p/11151457.html
Copyright © 2011-2022 走看看