Solution Set - CDQ分治&整体二分

A[洛谷P2163].给定平面上若干个点,多次询问给定矩形内的点数。
B[洛谷P3810].给定若干个三元组,对所有\(k\),求这样三元组的个数:恰有\(k\)个三元组,满足其每个分量都不超过它的相应分量。
C[洛谷P3157].给定一个序列,从中依次删去某些元素,求每次删除前逆序对数目。
D[CF762E/CF1045G].给定若干三元组\((x_i,r_i,f_i)\),求满足\(|x_i-x_j|\le \min(r_i,r_j)\)\(|f_i-f_j|\le k\)的无序对\((i,j)\)数目。
E[CF641E].维护一个带时间戳的multiset,要求在某时刻插入/删除某个数,询问某个数的个数。
F[洛谷P4390].维护一个平面,单点修改,矩形查询。
G[洛谷P4093].给定一个序列,可能发生若干种修改中的至多一种,修改形如将某个数改为某个值。求在所有情况下都是单调不减子序列的最长子序列。
H[洛谷P2487].给定两个序列,求一个最长的下标序列,使得其在两个序列都单调递减。在所有这样的序列中等概率取一个,求包含某个位置的概率。
I[洛谷P4027].给定两种金券在\(n\)天内的单价及初始钱数,每一天可以将所有的钱兑换两种金券(两种金券的比例给定),或者卖掉所有金券。求\(n\)天后的最大钱数。
J[洛谷P3206].给定一棵树,边有权,给定若干次修改某条边的权,求每次修改后的最小生成树边权和。
K[CF848C].给定一个序列,单点修改,询问某段区间中所有数最后一次出现位置减去第一次出现位置的值的和。
L[洛谷P6406].给定一个序列,求所有区间最小值,最大值和长度之积的和。
M[LOJ#2880].给定平面上若干个横、纵坐标互不相同的点,求这样的矩形数目:其左下角,右上角是给定点,内部没有给定点。
N[洛谷P3332].维护若干个可重集,要求在一段连续集合中加入一个数,询问一段连续集合的并集中的第\(k\)大值。
O[SPOJ-METEORS].一个环,每个点有一个类型,每个类型有一个目标,现在给环上若干区间加某个值,问每个类型的点权值和在那一次操作后达到目标。
P[洛谷P7424].给定若干区间,每个区间有一个目标,现在给某些位置加一,问每个区间内权值和何时达到目标。
Q[洛谷P2617].给定一个序列,单点修改,询问区间第\(k\)小值。


A离线询问,用二维前缀和转化,然后按照横坐标顺序加点和处理询问。
B是CDQ分治模板,用树状数组维护。
C将时间看作一位,还是模板。也可以用分块。
D先按照\(r\)排序,然后用双指针处理\(x\),用树状数组处理\(f\)
E直接用CDQ分治,开桶统计即可。
F用CDQ分治,中间使用A题思路。
G考虑DP,记录每个位置原始值\(a_i\),最小可能值\(b_i\),最大可能值\(c_i\),则\(dp_i=max\{dp_j\}+1\),其中\(j \le i,a_j \le b_i,c_j \le a_i\),用CDQ分治优化转移即可。
H和G类似。
I列出转移方程(很容易)后斜率优化,也用CDQ分治维护。
J对操作序列CDQ分治,处理每段序列时,将不会影响的边先处理——加入某些必选入最小生成树的边,然后缩点。用一个按秩合并的可撤销并查集维护。
K树套树,转化为对满足\(l \le i \le r,nxt_i \le r\)的所有\(i\)\(nxt_i - i\)之和。
L区间分治。枚举最小值的位置,假设在左边,记录右边最长扩展位置和每个位置的最大值,用两个堆维护。可以参考代码中的一句注释。
M用CDQ分治,先按横坐标排序,中间两边按纵坐标排序,维护两个单调栈。对右边每个点,有一段可能的纵坐标区间,二分求其在左边单调栈中的点数目。
N,O,P,Q都可以算作整体二分模板,只有Q需要注意修改方式是先删除再增加。


点击查看A题代码
#include<bits/stdc++.h>
using namespace std;
const int N=5e5+5,M=1e7+10;
int n,m,c[M],cnt,ans[N];
struct point{int x,y,no,ans;}a[N],q[N<<2];
bool operator <(const point &a,const point &b){
	if(a.x==b.x)return a.y<b.y;
	return a.x<b.x;
}
void add(int x){for(;x<=M-5;x+=x&-x)++c[x];}
int ask(int x){int res=0;for(;x;x-=x&-x)res+=c[x];return res;}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)scanf("%d%d",&a[i].x,&a[i].y);
	for(int i=1,x,y,z,w;i<=m;i++){
		scanf("%d%d%d%d",&x,&y,&z,&w);
		q[++cnt].x=x-1;q[cnt].y=y-1;q[cnt].no=i;q[cnt].ans=0;
		q[++cnt].x=x-1;q[cnt].y=w;q[cnt].no=-i;q[cnt].ans=0;
		q[++cnt].x=z;q[cnt].y=y-1;q[cnt].no=-i;q[cnt].ans=0;
		q[++cnt].x=z;q[cnt].y=w;q[cnt].no=i;q[cnt].ans=0;
	}
	sort(a+1,a+n+1);a[n+1].x=a[n+1].y=M-5;
	sort(q+1,q+4*m+1);
	int pos=0;
	for(int i=1;i<=n+1;i++){
		while(q[pos+1].x<a[i].x&&pos<cnt){
			++pos;
			q[pos].ans=ask(q[pos].y+2);
		}
		add(a[i].y+2);
	}
	for(int i=1;i<=4*m;i++){
		if(q[i].no>0)ans[q[i].no]+=q[i].ans;
		else ans[-q[i].no]-=q[i].ans;
	}
	for(int i=1;i<=m;i++)printf("%d\n",ans[i]);
	return 0;
}
点击查看B题代码
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int n,m,k,cnt[N],ans[N];
struct point{int x,y,z,res,cnt;}a[N],x[N];
bool cmp1(point a,point b){
	if(a.x!=b.x)return a.x<b.x;
	if(a.y!=b.y)return a.y<b.y;
	return a.z<b.z;
}
bool cmp2(point a,point b){
	if(a.y!=b.y)return a.y<b.y;
	return a.z<b.z;
}
struct BIT{
	int c[N+5];
	void modify(int x,int v){for(;x<=N;x+=x&-x)c[x]+=v;}
	int query(int x){int res=0;for(;x;x-=x&-x)res+=c[x];return res;}
}b;
void CDQ(int l,int r){
	if(l==r)return;
	int mid=l+r>>1,j=l;
	CDQ(l,mid);CDQ(mid+1,r);
	sort(a+l,a+mid+1,cmp2);
	sort(a+mid+1,a+r+1,cmp2);
	for(int i=mid+1;i<=r;i++){
		while(j<=mid&&a[j].y<=a[i].y)
			b.modify(a[j++].z,a[j].cnt);
		a[i].res+=b.query(a[i].z);
	}
	for(int i=l;i<j;i++)b.modify(a[i].z,-a[i].cnt);
}
int main(){
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;i++){
		scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);
		a[i].res=a[i].cnt=0;x[i]=a[i];
	}
	sort(x+1,x+n+1,cmp1);
	a[m=1]=x[1];a[1].cnt=1;
	for(int i=2;i<=n;i++){
		if(x[i].x!=a[m].x||x[i].y!=a[m].y||x[i].z!=a[m].z)a[++m]=x[i];
		++a[m].cnt;
	}
	CDQ(1,m);
	for(int i=1;i<=m;i++)ans[a[i].res+a[i].cnt]+=a[i].cnt;
	for(int i=1;i<=n;i++)printf("%d\n",ans[i]);
	return 0;
}
点击查看C题代码
//CDQ分治
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,m;long long ans[N];
struct point{int x,y,z;}a[N];
bool cmp1(point a,point b){return a.z<b.z;}
bool cmp2(point a,point b){return a.x<b.x;}
struct BIT{
	int c[N];
	void modify(int x,int v){for(;x<=n;x+=x&-x)c[x]+=v;}
	int query(int x){int res=0;for(;x;x-=x&-x)res+=c[x];return res;}
}b;
void CDQ(int l,int r){
	if(l==r)return;
	int mid=l+r>>1,i,j;
	CDQ(l,mid);CDQ(mid+1,r);
	sort(a+l,a+mid+1,cmp2);
	sort(a+mid+1,a+r+1,cmp2);
	for(i=l,j=mid+1;i<=mid;i++){
		while(j<=r&&a[j].x<a[i].x)
			b.modify(a[j++].y,1);
		ans[a[i].z]+=b.query(a[i].y);
	}
	for(i=mid+1;i<j;i++)b.modify(a[i].y,-1);
	for(i=mid,j=r;i>=l;i--){
		while(j>=mid+1&&a[j].x>a[i].x)
			b.modify(a[j--].y,1);
		ans[a[i].z]+=b.query(n)-b.query(a[i].y);
	}
	for(i=r;i>j;i--)b.modify(a[i].y,-1);
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1,x;i<=n;i++)scanf("%d",&x),a[x].y=i,a[i].x=n-i+1;
	for(int i=1,x;i<=m;i++)scanf("%d",&x),a[x].z=i;
	for(int i=1,j=m;i<=n;i++)if(!a[i].z)a[i].z=++j;
	sort(a+1,a+n+1,cmp1);
	CDQ(1,n);
	for(int i=n;i>=1;i--)ans[i]+=ans[i+1];
	for(int i=1;i<=m;i++)printf("%lld\n",ans[i]);
	return 0;
}



//分块
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5,B=500;
int n,m,a[N],p[N],b[N],f[N],t[N],c[N][B];ll cnt,ans[N];
void add(int x,int p){for(;x<=n;x+=x&-x)++c[x][p];}
int ask(int x,int p){int res=0;for(;x;x-=x&-x)res+=c[x][p];return res;}
void modify(int x){
	int id=(p[x]-1)/B+1;
	for(int i=1;i<id;i++)cnt+=ask(n,i)-ask(x,i);
	for(int i=(id-1)*B+1;i<p[x];i++)if(t[i]>x)++cnt;
	for(int i=p[x]+1;i<=id*B;i++)if(t[i]!=0&&t[i]<x)++cnt;
	for(int i=id+1;i<=n/B+1;i++)cnt+=ask(x,i);
	add(x,id);t[p[x]]=x;
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)scanf("%d",a+i),p[a[i]]=i;
	for(int i=1;i<=m;i++)scanf("%d",b+i),f[b[i]]=1;
	for(int i=1;i<=n;i++)if(!f[i])modify(i);
	for(int i=m;i>=1;i--)modify(b[i]),ans[i]=cnt;
	for(int i=1;i<=m;i++)printf("%lld\n",ans[i]);
	return 0;
}
点击查看D题代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,k,y[N],m;long long ans;
struct node{int x,r,f;}a[N];
bool cmp1(node a,node b){return a.r<b.r;}
bool cmp2(node a,node b){return a.x<b.x;}
bool cmp3(node a,node b){return a.x+a.r<b.x+b.r;}
bool cmp4(node a,node b){return a.x-a.r<b.x-b.r;}
struct BIT{
	int c[N+5],t[N+5],tim;
	void modify(int x,int v){
		x=lower_bound(y+1,y+m+1,x)-y;
		for(;x<=N;x+=x&-x)
			if(t[x]!=tim)c[x]=v,t[x]=tim;
			else c[x]+=v;
	}
	int query(int x){
		x=upper_bound(y+1,y+m+1,x)-y-1;
		int res=0;
		for(;x>0;x-=x&-x)if(t[x]==tim)res+=c[x];
		return res;
	}
}b;
void CDQ(int l,int r){
	if(l==r)return;
	int mid=l+r>>1;
	CDQ(l,mid);CDQ(mid+1,r);
	sort(a+mid+1,a+r+1,cmp2);
	sort(a+l,a+mid+1,cmp3);
	for(int i=l,j=mid+1;i<=mid;i++){
		while(j<=r&&a[j].x<=a[i].x+a[i].r)
			b.modify(a[j++].f,1);
		ans+=b.query(a[i].f+k)-b.query(a[i].f-k-1);
	}++b.tim;
	sort(a+l,a+mid+1,cmp4);
	for(int i=l,j=mid+1;i<=mid;i++){
		while(j<=r&&a[j].x<a[i].x-a[i].r)
			b.modify(a[j++].f,1);
		ans-=b.query(a[i].f+k)-b.query(a[i].f-k-1);
	}++b.tim;
}
int main(){
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;i++)
		scanf("%d%d%d",&a[i].x,&a[i].r,&a[i].f),y[i]=a[i].f;
	sort(a+1,a+n+1,cmp1);
	sort(y+1,y+n+1);m=unique(y+1,y+n+1)-y-1;
	CDQ(1,n);
	printf("%lld\n",ans);
	return 0;
}
点击查看E题代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,x[N],ans[N],cnt[N];
struct node{int op,t,x,id;}a[N];
bool cmp2(node a,node b){return a.t!=b.t?a.t<b.t:a.op<b.op;}
bool cmp3(node a,node b){return a.id<b.id;}
void CDQ(int l,int r){
	if(l==r)return;
	int mid=l+r>>1,j=l;
	CDQ(l,mid);CDQ(mid+1,r);
	for(int i=mid+1;i<=r;i++){
		while(j<=mid&&a[j].t<=a[i].t){
			if(a[j].op==1)cnt[a[j].x]++;
			if(a[j].op==2)cnt[a[j].x]--;
			j++;
		}
		if(a[i].op==3)ans[a[i].id]+=cnt[a[i].x];
	}
	for(int i=l;i<j;i++)cnt[a[i].x]=0;
	sort(a+l,a+r+1,cmp2);
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d%d%d",&a[i].op,&a[i].t,&a[i].x);
		x[i]=a[i].x;a[i].id=i;
	}
	sort(x+1,x+n+1);int m=unique(x+1,x+n+1)-x-1;
	for(int i=1;i<=n;i++)a[i].x=lower_bound(x+1,x+n+1,a[i].x)-x;
	CDQ(1,n);sort(a+1,a+n+1,cmp3);
	for(int i=1;i<=n;i++)if(a[i].op==3)printf("%d\n",ans[i]);
	return 0;
}
点击查看F题代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5,M=2e6+5;
int s,w,n;ll ans[N];
struct node{int op,a,b,c,d;}a[N];
struct point{int x,y,id;ll ans;}b[N],q[N<<2];
bool operator <(const point &a,const point &b){
	if(a.x==b.x)return a.y<b.y;
	return a.x<b.x;
}
struct BIT{
	ll c[M+5];int t[M+5],tim;
	void modify(int x,int v){
		for(;x<=M;x+=x&-x)
			if(t[x]!=tim)c[x]=v,t[x]=tim;
			else c[x]+=v;
	}
	int query(int x){
		ll res=0;
		for(;x>0;x-=x&-x)if(t[x]==tim)res+=c[x];
		return res;
	}
}B;
void CDQ(int l,int r){
	if(l==r)return;
	int mid=l+r>>1;
	CDQ(l,mid);CDQ(mid+1,r);
	int m=0,k=0;
	for(int i=l;i<=mid;i++)if(a[i].op==1){
		b[++m].x=a[i].a;b[m].y=a[i].b;
		b[m].id=a[i].c;
	}b[m+1].x=M;
	for(int i=mid+1;i<=r;i++)if(a[i].op==2){
		q[++k].x=a[i].a-1;q[k].y=a[i].b-1;q[k].id=i;q[k].ans=0;
		q[++k].x=a[i].a-1;q[k].y=a[i].d;q[k].id=-i;q[k].ans=0;
		q[++k].x=a[i].c;q[k].y=a[i].b-1;q[k].id=-i;q[k].ans=0;
		q[++k].x=a[i].c;q[k].y=a[i].d;q[k].id=i;q[k].ans=0;
	}
	sort(b+1,b+m+1);sort(q+1,q+k+1);++B.tim;
	for(int i=1,j=1;i<=m+1;i++){
		while(q[j].x<b[i].x&&j<=k)
			q[j].ans=B.query(q[j].y+2),j++;
		B.modify(b[i].y+2,b[i].id);
	}
	for(int i=1;i<=k;i++){
		if(q[i].id>0)ans[q[i].id]+=q[i].ans;
		else ans[-q[i].id]-=q[i].ans;
	}
}
int main(){
	scanf("%d%d",&n,&n);n=0;
	while(scanf("%d",&a[++n].op),a[n].op!=3){
		if(a[n].op==1)scanf("%d%d%d",&a[n].a,&a[n].b,&a[n].c);
		else scanf("%d%d%d%d",&a[n].a,&a[n].b,&a[n].c,&a[n].d);
	}--n;
	CDQ(1,n);
	for(int i=1;i<=n;i++)if(a[i].op==2)printf("%lld\n",ans[i]);
	return 0;
}
点击查看G题代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,m,a[N],mn[N],mx[N],f[N],id[N],ans;
struct BIT{
	int c[N+5],t[N+5],tim;
	void modify(int x,int v){
		for(;x<=N;x+=x&-x)
			if(t[x]!=tim)c[x]=v,t[x]=tim;
			else c[x]=max(c[x],v);
	}
	int query(int x){
		int res=0;
		for(;x>0;x-=x&-x)if(t[x]==tim)res=max(res,c[x]);
		return res;
	}
}b;
bool cmp1(int i,int j){return a[i]<a[j];}
bool cmp2(int i,int j){return mx[i]<mx[j];}
void CDQ(int l,int r){
	if(l==r){f[l]=max(f[l],1);return;}
	int mid=l+r>>1;
	CDQ(l,mid);
	sort(id+l,id+mid+1,cmp2);
	sort(id+mid+1,id+r+1,cmp1);
	++b.tim;
	for(int i=mid+1,j=l;i<=r;i++){
		while(j<=mid&&mx[id[j]]<=a[id[i]])
			b.modify(a[id[j]],f[id[j]]),j++;
		f[id[i]]=max(f[id[i]],b.query(mn[id[i]])+1);
	}
	sort(id+l,id+r+1);
	CDQ(mid+1,r);
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
		scanf("%d",a+i);
		mn[i]=mx[i]=a[i];id[i]=i;
	}
	for(int i=1,x,y;i<=m;i++){
		scanf("%d%d",&x,&y);
		mn[x]=min(mn[x],y);mx[x]=max(mx[x],y);
	}
	CDQ(1,n);
	for(int i=1;i<=n;i++)ans=max(ans,f[i]);
	printf("%d\n",ans);
	return 0;
}
点击查看H题代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,m,h[N],v[N],y[N],id[N];
struct node{int ans;double cnt;}f[N],g[N],ans;
node operator +(const node&a,const node&b){
	node c;
	if(a.ans==b.ans)c.ans=a.ans,c.cnt=a.cnt+b.cnt;
	else if(a.ans>b.ans)c=a;
	else c=b;
	return c;
}
struct BIT{
	node c[N+5];
	int t[N+5],tim;
	void modify(int x,node v){
		for(;x<=N;x+=x&-x)
			if(t[x]!=tim)c[x]=v,t[x]=tim;
			else c[x]=c[x]+v;
	}
	node query(int x){
		node res;res.cnt=res.ans=0;
		for(;x>0;x-=x&-x)if(t[x]==tim)res=res+c[x];
		return res;
	}
}B;
bool cmp(int i,int j){return h[i]<h[j];}
void CDQ(int l,int r,node x[]){
	if(l==r){x[l]=x[l]+node{1,1};return;}
	int mid=l+r>>1;
	CDQ(l,mid,x);
	sort(id+l,id+mid+1,cmp);
	sort(id+mid+1,id+r+1,cmp);
	++B.tim;
	for(int i=mid+1,j=l;i<=r;i++){
		while(j<=mid&&h[id[j]]<=h[id[i]])
			B.modify(v[id[j]],x[id[j]]),++j;
		node tmp=B.query(v[id[i]]);++tmp.ans;
		x[id[i]]=x[id[i]]+tmp;
	}
	for(int i=l;i<=r;i++)id[i]=i;
	CDQ(mid+1,r,x);
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d%d",h+i,v+i);id[i]=i;
		h[i]=-h[i];v[i]=-v[i];y[i]=v[i];
	}
	sort(y+1,y+n+1);int m=unique(y+1,y+n+1)-y-1;
	for(int i=1;i<=n;i++)v[i]=lower_bound(y+1,y+m+1,v[i])-y;
	CDQ(1,n,f);
	for(int i=1;i<=n;i++)h[i]=-h[i],v[i]=m+1-v[i];
	reverse(h+1,h+n+1);reverse(v+1,v+n+1);
	CDQ(1,n,g);
	for(int i=1;i<=n;i++)ans=ans+f[i];
	printf("%d\n",ans.ans);
	for(int i=1;i<=n;i++)
		if(f[i].ans+g[n-i+1].ans-1==ans.ans)
			printf("%.5lf ",f[i].cnt*g[n-i+1].cnt/ans.cnt);
		else printf("0.00000 ");
	return 0;
}
点击查看I题代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,s,id[N],q[N],he,ta;
double a[N],b[N],c[N],x[N],y[N],dp[N],ans;
bool cmp1(int i,int j){return x[i]!=x[j]?x[i]<x[j]:y[i]>y[j];}
bool cmp2(int i,int j){return a[i]/b[i]<a[j]/b[j];}
void CDQ(int l,int r){
	if(l==r){dp[l]=max(dp[l],dp[l-1]);return;}
	int mid=l+r>>1;
	CDQ(l,mid);
	for(int i=l;i<=mid;i++){
		x[i]=dp[i]*c[i]/(a[i]*c[i]+b[i]);
		y[i]=dp[i]/(a[i]*c[i]+b[i]);
	}
	for(int i=l;i<=r;i++)id[i]=i;
	sort(id+l,id+mid+1,cmp1);
	sort(id+mid+1,id+r+1,cmp2);
	he=1;ta=0;
	for(int j=l;j<=mid;j++){
		if(x[id[j]]==x[q[ta]])continue;
		while(he<ta){
			int p1=q[ta-1],p2=q[ta];
			if((y[p1]-y[p2])/(x[p2]-x[p1])>(y[p1]-y[id[j]])/(x[id[j]]-x[p1]))--ta;
			else break;
		}
		q[++ta]=id[j];
	}
	for(int i=mid+1;i<=r;i++){
		while(he<ta){
			int p1=q[he],p2=q[he+1];
			if(x[p1]*a[id[i]]+y[p1]*b[id[i]]<x[p2]*a[id[i]]+y[p2]*b[id[i]])++he;
			else break;
		}
		dp[id[i]]=max(dp[id[i]],x[q[he]]*a[id[i]]+y[q[he]]*b[id[i]]);
	}
	CDQ(mid+1,r);
}
int main(){
	scanf("%d%d",&n,&s);
	for(int i=1;i<=n;i++)
		scanf("%lf%lf%lf",a+i,b+i,c+i);
	dp[0]=s;CDQ(1,n);
	for(int i=1;i<=n;i++)ans=max(ans,dp[i]);
	printf("%.3lf\n",ans);
	return 0;
}
点击查看J题代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e4+5,M=5e4+5;
int n,m,q;
struct disjoint_set{
	int fa[N],sz[N],st[M][2],top;
	void init(){for(int i=1;i<=n;i++)fa[i]=i,sz[i]=1;}
	int find(int x){return (fa[x]==x?x:find(fa[x]));}
	void Union(int x,int y){
		int u=find(x),v=find(y);
		if(u==v)return;
		if(sz[u]<sz[v])swap(u,v);
		sz[u]+=sz[v];fa[v]=u;
		st[++top][0]=u;st[top][1]=v;
	}
	void remove(){
		int u=st[top][0],v=st[top][1];--top;
		sz[u]-=sz[v];fa[v]=v;
	}
	void clear(int tim){while(top>tim)remove();}
}S,S1;
struct edge{int u,v;ll w;int mark;}e[M];
bool operator <(const edge&a,const edge&b){return a.w<b.w;}
vector<edge>ve[30],vq,tr;ll res[30];int tim[30];bool f[M];
struct query{int num;ll val,ans;}p[M];
void push_down(int dep){
	tr.clear();
	for(int i=0;i<ve[dep].size();i++)tr.push_back(ve[dep][i]);
	sort(tr.begin(),tr.end());
	for(int i=0;i<tr.size();i++){
		if(S1.find(tr[i].u)==S1.find(tr[i].v))tr[i].mark=-1;
		else S1.Union(tr[i].u,tr[i].v);
	}S1.clear(0);res[dep+1]=res[dep];
	for(int i=0;i<vq.size();i++)S1.Union(vq[i].u,vq[i].v);vq.clear();
	for(int i=0;i<tr.size();i++)
		if(tr[i].mark!=-1&&S1.find(tr[i].u)!=S1.find(tr[i].v)){
			tr[i].mark=1;S1.Union(tr[i].u,tr[i].v);
			S.Union(tr[i].u,tr[i].v);res[dep+1]+=tr[i].w;
		}
	S1.clear(0);ve[dep+1].clear();
	for(int i=0,u,v;i<tr.size();i++)
		if(!tr[i].mark&&(u=S.find(tr[i].u))!=(v=S.find(tr[i].v)))
			ve[dep+1].push_back({u,v,tr[i].w,0});
}
void CDQ(int l,int r,int dep){
	if(l==r){
		ve[dep].push_back({S.find(e[p[l].num].u),S.find(e[p[l].num].v),p[l].val,0});
		e[p[l].num].w=p[l].val;push_down(dep);
		p[l].ans=res[dep+1];S.clear(tim[dep-1]);
		return;
	}
	tim[dep]=S.top;int mid=l+r>>1;
	for(int i=l;i<=mid;i++)f[p[i].num]=true;
	for(int i=mid+1,id;i<=r;i++)if(!f[id=p[i].num])
		ve[dep].push_back({S.find(e[id].u),S.find(e[id].v),e[id].w,0});
	for(int i=l;i<=mid;i++)
		vq.push_back({S.find(e[p[i].num].u),S.find(e[p[i].num].v),0,0});
	push_down(dep);
	for(int i=mid+1;i<=r;i++)if(!f[p[i].num])ve[dep].pop_back();
	for(int i=l;i<=mid;i++)f[p[i].num]=false;CDQ(l,mid,dep+1);
	for(int i=0;i<ve[dep].size();i++)ve[dep][i].mark=0;
	for(int i=mid+1;i<=r;i++)f[p[i].num]=true;
	for(int i=l,id;i<=mid;i++)if(!f[id=p[i].num])
		ve[dep].push_back({S.find(e[id].u),S.find(e[id].v),e[id].w,0});
	for(int i=mid+1;i<=r;i++){
		f[p[i].num]=0;
		vq.push_back({S.find(e[p[i].num].u),S.find(e[p[i].num].v),0,0});
	}
	push_down(dep);CDQ(mid+1,r,dep+1);
	S.clear(tim[dep-1]);
}
int main(){
	scanf("%d%d%d",&n,&m,&q);S.init();S1.init();
	for(int i=1;i<=m;i++)scanf("%d%d%lld",&e[i].u,&e[i].v,&e[i].w);
	for(int i=1;i<=q;i++)scanf("%d%lld",&p[i].num,&p[i].val);
	for(int i=1;i<=q;i++){
		int id=p[i].num;f[id]=true;
		vq.push_back({e[id].u,e[id].v,0,0});
	}
	for(int i=1;i<=m;i++)if(!f[i])ve[1].push_back(e[i]);
	for(int i=1;i<=q;i++)f[p[i].num]=false;
	CDQ(1,q,1);
	for(int i=1;i<=q;i++)printf("%lld\n",p[i].ans);
	return 0;
}
点击查看K题代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5;
int n,q,a[N],lst[N],nxt[N],now[N];
int root[N],lc[N*100],rc[N*100],tot;ll sum[N*100];
int new_node(){
	++tot;
	lc[tot]=rc[tot]=0;
	return tot;
}
void modify(int p,int l,int r,int x,int v){
	if(l==r){sum[p]+=v;return;}
	int mid=l+r>>1;
	if(x<=mid){
		if(!lc[p])lc[p]=new_node();
		modify(lc[p],l,mid,x,v);
	}
	else{
		if(!rc[p])rc[p]=new_node();
		modify(rc[p],mid+1,r,x,v);
	}
	sum[p]=sum[lc[p]]+sum[rc[p]];
}
ll query(int p,int l,int r,int L,int R){
	if(!p)return 0;
	if(l>=L&&r<=R)return sum[p];
	int mid=l+r>>1;ll res=0;
	if(L<=mid)res+=query(lc[p],l,mid,L,R);
	if(R>mid)res+=query(rc[p],mid+1,r,L,R);
	return res;
}
void add(int x,int y,int v){for(;x<=n;x+=x&-x)modify(root[x],1,n+1,y,v);}
ll ask(int x,int y){ll res=0;for(;x;x-=x&-x)res+=query(root[x],1,n+1,1,y);return res;}
set<int> S[N];
int main(){
	scanf("%d%d",&n,&q);
	for(int i=1;i<=n;i++)nxt[i]=n+1;
	for(int i=1;i<=n;i++){
		scanf("%d",a+i);
		lst[i]=now[a[i]];
		nxt[lst[i]]=i;
		now[a[i]]=i;
		S[a[i]].insert(i);
	}
	for(int i=1;i<=n;i++)root[i]=new_node();
	for(int i=1;i<=n;i++)add(i,nxt[i],nxt[i]-i);
	for(int i=1,op,l,r;i<=q;i++){
		scanf("%d%d%d",&op,&l,&r);
		if(op==1){
			lst[nxt[l]]=lst[l];
			nxt[lst[l]]=nxt[l];
			if(lst[l]){
				add(lst[l],l,-(l-lst[l]));
				add(lst[l],nxt[l],nxt[l]-lst[l]);
			}
			add(l,nxt[l],-(nxt[l]-l));
			S[a[l]].erase(S[a[l]].find(l));
			auto it=S[r].lower_bound(l);
			nxt[l]=(it==S[r].end()?n+1:*it);
			lst[l]=(it==S[r].begin()?0:*--it);
			nxt[lst[l]]=l;lst[nxt[l]]=l;
			add(l,nxt[l],nxt[l]-l);
			if(lst[l]){
				add(lst[l],nxt[l],-(nxt[l]-lst[l]));
				add(lst[l],l,l-lst[l]);
			}
			S[r].insert(l);a[l]=r;
		}
		else printf("%lld\n",ask(n,r)-ask(l-1,r));
	}
	return 0;
}
点击查看L题代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> pll;
const int N=5e5+5,mod=1e9;
int n;ll a[N];
priority_queue<pll,vector<pll>,greater<pll> > Q1,Q2;
ll solve(int l,int r){
	if(l==r)return a[l]*a[l]%mod;
	int mid=l+r>>1;
	ll ans=(solve(l,mid)+solve(mid+1,r))%mod;
	while(!Q1.empty())Q1.pop();while(!Q2.empty())Q2.pop();
	ll s1=0,s2=0,s3=0;
	//Q1记比mx小的值,Q2记比mx大的值
	//s1记Q1的位置和,s2记Q2的元素和,s3记Q2的元素与位置之积的和 
	ll mn=1e9,mx=0,mx2=0;
	for(int i=mid+1,p=mid;i<=r;i++){
		mn=min(mn,a[i]);mx=max(mx,a[i]);
		while(!Q2.empty()&&Q2.top().first<mx){
			ll val=Q2.top().first,pos=Q2.top().second;Q2.pop();
			s2=(s2-val+mod)%mod;s3=(s3-val*pos%mod+mod)%mod;
			Q1.push(make_pair(val,pos));s1+=pos;
		}
		while(p>=l&&a[p]>=mn){
			mx2=max(mx2,a[p]);
			if(mx2<mx)Q1.push(make_pair(mx2,mid-p+1)),s1=(s1+(mid-p+1))%mod;
			else{
				Q2.push(make_pair(mx2,mid-p+1));
				s2=(s2+mx2)%mod;s3=(s3+mx2*(mid-p+1)%mod)%mod;
			}
			--p;
		}
		ans=(ans+(1ll*Q1.size()*(i-mid)+s1)%mod*mn%mod*mx%mod+
				 mn*s3%mod+mn*s2%mod*(i-mid)%mod)%mod;
	}
	while(!Q1.empty())Q1.pop();while(!Q2.empty())Q2.pop();
	mn=1e9;mx=mx2=0;s1=s2=s3=0;
	for(int i=mid,p=mid+1;i>=l;i--){
		mn=min(mn,a[i]);mx=max(mx,a[i]);
		while(!Q2.empty()&&Q2.top().first<=mx){
			ll val=Q2.top().first,pos=Q2.top().second;Q2.pop();
			s2=(s2-val+mod)%mod;s3=(s3-val*pos%mod+mod)%mod;
			Q1.push(make_pair(val,pos));s1+=pos;
		}
		while(p<=r&&a[p]>mn){
			mx2=max(mx2,a[p]);
			if(mx2<=mx)Q1.push(make_pair(mx2,p-mid)),s1=(s1+(p-mid))%mod;
			else{
				Q2.push(make_pair(mx2,p-mid));
				s2=(s2+mx2)%mod;s3=(s3+mx2*(p-mid)%mod)%mod;
			}
			++p;
		}
		ans=(ans+(1ll*Q1.size()*(mid-i+1)+s1)%mod*mn%mod*mx%mod+
				 mn*s3%mod+mn*s2%mod*(mid-i+1)%mod)%mod;
	}
	return ans;
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++)scanf("%lld",a+i);
	printf("%lld\n",solve(1,n));
	return 0;
}
点击查看M题代码
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int n,st[N],q[N];long long ans;
struct point{int x,y;}a[N];
bool cmp1(point a,point b){return a.x<b.x;}
bool cmp2(point a,point b){return a.y<b.y;}
void CDQ(int l,int r){
	if(l==r)return;
	int mid=l+r>>1;
	CDQ(l,mid);CDQ(mid+1,r);
	sort(a+l,a+mid+1,cmp2);
	sort(a+mid+1,a+r+1,cmp2);
	int top=0,he=1,ta=0;
	for(int i=mid+1,j=l;i<=r;i++){
		while(top&&a[i].x<a[st[top]].x)--top;
		int d=a[st[top]].y;st[++top]=i;
		while(j<=mid&&a[j].y<a[i].y){
			while(he<=ta&&a[q[ta]].x<a[j].x)--ta;
			q[++ta]=j;++j;
		}
		int L=1,R=ta,he=ta+1;
		while(L<=R){
			int Mid=L+R>>1;
			if(a[q[Mid]].y>d)R=Mid-1,he=Mid;
			else L=Mid+1;
		}
		ans+=ta-he+1;
	}
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++)scanf("%d%d",&a[i].x,&a[i].y);
	sort(a+1,a+n+1,cmp1);a[0].x=a[0].y=-1;
	CDQ(1,n);
	printf("%lld\n",ans);
	return 0;
}
点击查看N题代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e4+5;
int n,m;
struct Query{int op,l,r;ll c;int ans;}a[N];
vector<int> q;
struct SegmentTree{
	int lc[N<<3],rc[N<<3],tot;ll sum[N<<3],add[N<<3];
	void init(){tot=0;new_node();}
	int new_node(){
		++tot;
		lc[tot]=rc[tot]=sum[tot]=add[tot]=0;
		return tot;
	}
	void push_up(int p){sum[p]=sum[lc[p]]+sum[rc[p]];}
	void push_down(int p,int l,int r){
		if(!add[p])return;
		ll v=add[p];add[p]=0;int mid=l+r>>1;
		sum[lc[p]]+=v*(mid-l+1);sum[rc[p]]+=v*(r-mid);
		add[lc[p]]+=v;add[rc[p]]+=v;
	}
	void modify(int p,int l,int r,int L,int R,ll v){
		if(!lc[p])lc[p]=new_node();
		if(!rc[p])rc[p]=new_node();
		push_down(p,l,r);
		if(l>=L&&r<=R){
			sum[p]+=(r-l+1)*v;add[p]+=v;
			return;
		}
		int mid=l+r>>1;
		if(L<=mid)modify(lc[p],l,mid,L,R,v);
		if(R>mid)modify(rc[p],mid+1,r,L,R,v);
		push_up(p);
	}
	ll query(int p,int l,int r,int L,int R){
		if(!p)return 0;
		if(!lc[p])lc[p]=new_node();
		if(!rc[p])rc[p]=new_node();
		push_down(p,l,r);
		if(l>=L&&r<=R)return sum[p];
		ll res=0;int mid=l+r>>1;
		if(L<=mid)res+=query(lc[p],l,mid,L,R);
		if(R>mid)res+=query(rc[p],mid+1,r,L,R);
		return res;
	}
}seg;
void solve(int l,int r,vector<int> q){
	if(l==r){
		for(auto x:q)a[x].ans=l;
		return;
	}
	int mid=l+r>>1;
	vector<int> ql,qr;seg.init();
	for(auto x:q){
		if(a[x].op==1){
			if(a[x].c<=mid)ql.push_back(x);
			else{
				seg.modify(1,1,n,a[x].l,a[x].r,1);
				qr.push_back(x);
			}
		}
		else{
			ll tmp=seg.query(1,1,n,a[x].l,a[x].r);
			if(tmp>=a[x].c)qr.push_back(x);
			else{a[x].c-=tmp;ql.push_back(x);}
		}
	}
	solve(l,mid,ql);solve(mid+1,r,qr);
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++){
		scanf("%d%d%d%lld",&a[i].op,&a[i].l,&a[i].r,&a[i].c);
		if(a[i].op==1)a[i].c+=n+1;q.push_back(i);
	}
	solve(1,2*n+1,q);
	for(auto x:q)if(a[x].op==2)printf("%d\n",a[x].ans-n-1);
	return 0;
}
点击查看O题代码
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
const int N=3e5+5;
int n,m,k,ans[N];ull p[N];
struct node{int l,r;ull x;}a[N];
vector<int> q,pos[N];
struct BIT{
	ull c[N+5];int t[N+5],tim;
	void modify(int x,ull v){
		for(;x<=m;x+=x&-x)
			if(t[x]!=tim)c[x]=v,t[x]=tim;
			else c[x]+=v;
	}
	ull query(int x){
		ull res=0;
		for(;x>0;x-=x&-x)if(t[x]==tim)res+=c[x];
		return res;
	}
}B;
void solve(int l,int r,vector<int> q){
	if(l==r){
		for(auto x:q)ans[x]=l;
		return;
	}
	int mid=l+r>>1;
	vector<int> ql,qr;B.tim++;
	for(int i=l;i<=mid;i++){
		if(a[i].l<=a[i].r)B.modify(a[i].l,a[i].x),B.modify(a[i].r+1,-a[i].x);
		else B.modify(1,a[i].x),B.modify(a[i].r+1,-a[i].x),B.modify(a[i].l,a[i].x);
	}
	for(auto x:q){
		ull tmp=0;
		for(auto y:pos[x])tmp+=B.query(y);
		if(tmp>=p[x])ql.push_back(x);
		else{p[x]-=tmp;qr.push_back(x);}
	}
	solve(l,mid,ql);solve(mid+1,r,qr);
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1,x;i<=m;i++){scanf("%d",&x);pos[x].push_back(i);}
	for(int i=1;i<=n;i++){scanf("%d",p+i);q.push_back(i);ans[i]=-1;}
	scanf("%d",&k);
	for(int i=1;i<=k;i++)
		scanf("%d%d%llu",&a[i].l,&a[i].r,&a[i].x);
	a[k+1].l=a[k+1].r=1;a[k+1].x=0;
	solve(1,k+1,q);
	for(auto x:q){
		if(ans[x]!=k+1)printf("%d\n",ans[x]);
		else puts("NIE");
	}
	return 0;
}
点击查看P题代码
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int n,m,b[N],ans[N];
struct wood{int l,r,s;}a[N];
vector<int> q;
struct BIT{
	int c[N+5],t[N+5],tim;
	void modify(int x,int v){
		for(;x<=N;x+=x&-x)
			if(t[x]!=tim)c[x]=v,t[x]=tim;
			else c[x]+=v;
	}
	int query(int x){
		int res=0;
		for(;x>0;x-=x&-x)if(t[x]==tim)res+=c[x];
		return res;
	}
}B;
void solve(int l,int r,vector<int> q){
	if(l==r){ans[l]=q.size();return;}
	int mid=l+r>>1;
	vector<int> ql,qr;
	++B.tim;
	for(int i=l;i<=mid;i++)B.modify(b[i],1);
	for(auto x:q){
		int y=B.query(a[x].r)-B.query(a[x].l-1);
		if(y>=a[x].s)ql.push_back(x);
		else{a[x].s-=y;qr.push_back(x);}
	}
	solve(l,mid,ql);solve(mid+1,r,qr);
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
		scanf("%d%d%d",&a[i].l,&a[i].r,&a[i].s);
		q.push_back(i);
	}
	for(int i=1;i<=m;i++)scanf("%d",b+i);
	b[m+1]=0;solve(1,m+1,q);
	for(int i=1;i<=m;i++)printf("%d\n",ans[i]);
	return 0;
}
点击查看Q题代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int n,m,b[N],r[N],k;char ch;
struct Query{int op,l,r,v,ans;}a[N];
vector<int> q;
struct BIT{
	int c[N+5],t[N+5],tim;
	void modify(int x,int v){
		for(;x<=N;x+=x&-x)
			if(t[x]!=tim)c[x]=v,t[x]=tim;
			else c[x]+=v;
	}
	int query(int x){
		int res=0;
		for(;x>0;x-=x&-x)if(t[x]==tim)res+=c[x];
		return res;
	}
}B;
void solve(int l,int r,vector<int> q){
	if(l==r){
		for(auto x:q)a[x].ans=l;
		return;
	}
	int mid=l+r>>1;
	vector<int> ql,qr;
	B.tim++;
	for(auto x:q){
		if(a[x].op==1){
			if(a[x].v<=mid){
				B.modify(a[x].l,a[x].r);
				ql.push_back(x);
			}
			else qr.push_back(x);
		}
		else{
			int y=B.query(a[x].r)-B.query(a[x].l-1);
			if(y>=a[x].v)ql.push_back(x);
			else{a[x].v-=y;qr.push_back(x);}
		}
	}
	solve(l,mid,ql);solve(mid+1,r,qr);
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
		scanf("%d",b+i);
		a[i].op=1;a[i].l=i;a[i].r=1;a[i].v=b[i];
		q.push_back(i);r[++k]=b[i];
	}
	int c=n;
	for(int i=1;i<=m;i++){
		while(ch=getchar(),ch!='Q'&&ch!='C');
		if(ch=='Q'){
			a[++c].op=2;
			scanf("%d%d%d",&a[c].l,&a[c].r,&a[c].v);
		}
		else{
			int x,y;
			scanf("%d%d",&x,&y);r[++k]=y;
			a[++c].op=1;a[c].l=x;a[c].r=-1;a[c].v=b[x];
			a[++c].op=1;a[c].l=x;a[c].r=1;a[c].v=b[x]=y;
		}
	}
	for(int i=n+1;i<=c;i++)q.push_back(i);
	sort(r+1,r+k+1);k=unique(r+1,r+k+1)-r-1;
	for(int i=1;i<=c;i++)if(a[i].op==1)
		a[i].v=lower_bound(r+1,r+k+1,a[i].v)-r;
	solve(1,k,q);
	for(auto x:q)if(a[x].op==2)printf("%d\n",r[a[x].ans]);
	return 0;
}
posted @ 2023-05-18 22:22  by_chance  阅读(22)  评论(0编辑  收藏  举报