zoukankan      html  css  js  c++  java
  • 路灯「APIO 2019」

    题意

    有、复杂,自己上网搜


    思路

    ((x,y)) 表示从(x)(y)联通的时间长度。

    那么查询操作相当于二维平面上的单点查询。

    对于每一个(i),维护一个最左能到达的(lm),和最右能到达的(rm)

    那么对于每一个更新操作,相当于对左上角为((lm,i)),右下角为((i,rm))的矩形做修改。

    于是就转换为类似「简单题」的题目了,可以CDQ分治解决,当然也可以直接上树套树。

    代码

    #include <bits/stdc++.h>
    
    using namespace std;
    
    namespace StandardIO {
    	
    	template<typename T> inline void read (T &x) {
    		x=0;T f=1;char c=getchar();
    		for (; c<'0'||c>'9'; c=getchar()) if (c=='-') f=-1;
    		for (; c>='0'&&c<='9'; c=getchar()) x=x*10+c-'0';
    		x*=f;
    	}
    	template<typename T> inline void write (T x) {
    		if (x<0) putchar('-'),x=-x;
    		if (x>=10) write(x/10);
    		putchar(x%10+'0');
    	}
    	
    }
    
    using namespace StandardIO;
    
    namespace Solve {
    	#define int long long
    	
    	const int N=300003;
    	
    	int n,q,sta,cnt;
    	char s[N];
    	int tree[N];
    	struct node {
    		int t,x,y,id;
    		int type,val,ans;
    		node () {}
    		node (int _t,int _x,int _y,int _ty,int _v,int _i) : t(_t),x(_x),y(_y),type(_ty),val(_v),id(_i) {}
    	} w[N<<2],tmp[N<<2];
    	int isQuery[N],ans[N];
    	set<int> S;
    	
    	inline int pre (int x) {
    		set<int>::iterator it=S.lower_bound(x);
    		return *(--it);
    	}
    	inline int suc (int x) {
    		set<int>::iterator it=S.upper_bound(x);
    		return *it;
    	}
    	inline int lowbit (int x) {
    		return x&(-x);
    	}
    	inline void update (int x,int v) {
    		for (register int i=x; i<=n; i+=lowbit(i)) {
    			tree[i]+=v;
    		}
    	}
    	inline int query (int x) {
    		int res=0;
    		for (register int i=x; i; i-=lowbit(i)) {
    			res+=tree[i];
    		}
    		return res;
    	}
    	inline bool cmpt (const node &x,const node &y) {
    		if (x.t!=y.t) return x.t<y.t;
    		if (x.x!=y.x) return x.x<y.x;
    		return x.y<y.y;
    	}
    	inline bool cmpx (const node &x,const node &y) {
    		if (x.x!=y.x) return x.x<y.x;
    		return x.y<y.y;
    	}
    	void merge (int l,int r) {
    		int mid=(l+r)>>1;
    		int ptr_l=l,ptr_r=mid+1,num=l-1;
    		while (ptr_l<=mid&&ptr_r<=r) {
    			if (cmpx(w[ptr_l],w[ptr_r])) tmp[++num]=w[ptr_l++];
    			else tmp[++num]=w[ptr_r++];
    		}
    		while (ptr_l<=mid) tmp[++num]=w[ptr_l++];
    		while (ptr_r<=r) tmp[++num]=w[ptr_r++];
    		for (register int i=l; i<=r; ++i) w[i]=tmp[i];
    	}
    	void CDQ (int l,int r) {
    		if (l==r) return;
    		int mid=(l+r)>>1;
    		CDQ(l,mid),CDQ(mid+1,r);
    		int ptr=l-1;
    		for (register int i=mid+1; i<=r; ++i) {
    			while (ptr<mid&&w[ptr+1].x<=w[i].x) {
    				++ptr;
    				if (w[ptr].type==1) update(w[ptr].y,w[ptr].val);
    			}
    			if (w[i].type==2) w[i].ans+=query(w[i].y);
    		}
    		for (register int i=l; i<=ptr; ++i) {
    			if (w[i].type==1) update(w[i].y,-w[i].val);
    		}
    		merge(l,r);
    	}
    	inline void MAIN () {
    		read(n),read(q);
    		S.insert(0),S.insert(n+1);
    		scanf("%s",s+1);
    		for (register int i=1; i<=n; ++i) {
    			if (s[i]=='0') {
    				S.insert(i);
    			}
    		}
    		for (register int i=1; i<=q; ++i) {
    			string op;int x,y;
    			cin>>op;
    			if (op[0]=='t') {
    				read(x),s[x]^=1;
    				int l=pre(x)+1,r=suc(x)-1;
    //				cout<<l<<' '<<r<<endl;
    				if (s[x]=='0') {
    					w[++cnt]=node(i,l,x,1,i,19);
    					w[++cnt]=node(i,l,r+1,1,-i,260);
    					w[++cnt]=node(i,x+1,x,1,-i,8);
    					w[++cnt]=node(i,x+1,r+1,1,i,17);
    					S.insert(x);
    				} else {
    					w[++cnt]=node(i,l,x,1,-i,19);
    					w[++cnt]=node(i,l,r+1,1,i,260);
    					w[++cnt]=node(i,x+1,x,1,i,8);
    					w[++cnt]=node(i,x+1,r+1,1,-i,17);
    					S.erase(x);
    				}
    			} else {
    				read(x),read(y);
    				isQuery[i]=1,++sta;
    				// node (int _t,int _x,int _y,int _ty,int _v,int _i) : t(_t),x(_x),y(_y),type(_ty),val(_v),id(_i) {}
    				w[++cnt]=node(i,x,y-1,2,0,sta);
    				if (suc(x)>y-1&&s[x]=='1'&&s[y-1]=='1') ans[sta]+=i;
    			}
    		}
    		sort(w+1,w+cnt+1,cmpt);
    //		for (register int i=1; i<=cnt; ++i) {
    //			write(w[i].y),putchar('
    ');
    //		}
    		CDQ(1,cnt);
    		for (register int i=1; i<=cnt; ++i) {
    			if (w[i].type==2) {
    				ans[w[i].id]+=w[i].ans;
    			}
    		}
    		for (register int i=1; i<=sta; ++i) {
    			write(ans[i]),putchar('
    ');
    		}
    	}
    	
    	#undef int
    }
    
    int main () {
    	Solve::MAIN();
    }
    
  • 相关阅读:
    Redis基础
    Ajax&Json
    Docker基础修炼3--Docker容器及常用命令
    Docker基础修炼2--Docker镜像原理及常用命令
    Docker基础修炼1--Docker简介及快速入门体验
    linux入门系列20--Web服务之LNMP架构实战
    linux入门系列19--数据库管理系统(DBMS)之MariaDB
    linux入门系列18--Web服务之Apache服务2
    linux入门系列18--Web服务之Apache服务1
    linux入门系列17--邮件系统之Postfix和Dovecot
  • 原文地址:https://www.cnblogs.com/ilverene/p/11395880.html
Copyright © 2011-2022 走看看