纯分块做法求卡常
查看原帖
纯分块做法求卡常
108510
Terminus_Est楼主2020/8/24 14:00

RT

虽然蒟蒻我是个大常数选手 但是这题真的好卡常啊 好像很多人都被卡常了(

今天都交了一板多了 卡常杀我也

求大佬帮忙卡常

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int read(){
    int x=0;
    char ch=getchar();
    while(ch<'0'||ch>'9'){ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x;
}
int n,m;
int len;
int num;
int bel[100010];
int st[320],ed[320];
int a[100010];
int maxpos[320][100010];
int m1[320][320][320];
int m2[320][100010];
int m3[320][320];
int m4[320][320][320];
ll m5[320][320][320];
int m6[320][320][320];
struct node{
	int pos;
	int val;
};
vector<node> tmp;
bool operator <(node a,node b){
	return a.val<b.val;
}
void pre(){
	len=sqrt(n);
	for(int i=1;i<=n;i+=len){
		st[++num]=i,ed[num]=min(i+len-1,n);
		for(int j=i;j<=i+len-1&&j<=n;++j){
			bel[j]=num;
		}
	}
	for(int i=1;i<=num;++i){
		tmp.clear();
		for(int j=st[i];j<=ed[i];++j){
			tmp.push_back({j-st[i]+1,a[j]});
		}
		sort(tmp.begin(),tmp.end());
		int now=1;
		while(now<tmp[0].val&&now<=n){
			maxpos[i][now]=0;
			now++;
		}
		for(int j=0;j<tmp.size();++j){
			while((j==tmp.size()-1&&now<=n)||now<tmp[j+1].val){
				maxpos[i][now]=j+1;
				now++;
			}
			m1[i][tmp[j].pos][j+1]++;
			for(int k=0;k<j;++k){
				if(tmp[k].pos<tmp[j].pos){
					m3[i][j+1]++;
					m6[i][k+1][j+1]++;
				}
			}
		}
		for(int j=1;j<=ed[i]-st[i]+1;++j){
			for(int k=1;k<=ed[i]-st[i]+1;++k){
				m1[i][j][k]+=m1[i][j-1][k]+m1[i][j][k-1]-m1[i][j-1][k-1];
			}
		}
		for(int j=1;j<=n;++j){
			m2[i][j]=m1[i][ed[i]-st[i]+1][maxpos[i][j]];
			m2[i][j]+=m2[i-1][j];
		}
		for(int j=0;j<tmp.size();++j){
			m3[i][j+1]+=m3[i][j];
		}
		for(int j=1;j<i;++j){
			for(int k=0;k<tmp.size();++k){
				m4[i][j][k+1]+=m4[i][j-1][k+1]+(m2[j][tmp[k].val]-m2[j-1][tmp[k].val]);
				m5[i][j][k+1]+=0ll+m5[i][j][k]+m4[i][j][k+1];
			}
		}
		for(int j=0;j<tmp.size();++j){
			for(int k=0;k<tmp.size();++k){
				m6[i][j+1][k+1]+=m6[i][j][k+1]+m6[i][j+1][k]-m6[i][j][k];
			}
		}
	}
}
ll query(int l,int r,int d,int u){
	ll ret=0;
	if(bel[l]==bel[r]){
		int bl=bel[l];
		for(int i=l;i<=r;++i){
			if(a[i]<d||a[i]>u)continue;
			ret+=0ll
				+m1[bl][i-st[bl]+1][maxpos[bl][a[i]-1]]
				-m1[bl][l-st[bl]][maxpos[bl][a[i]-1]]
				-m1[bl][i-st[bl]+1][maxpos[bl][d-1]]
				+m1[bl][l-st[bl]][maxpos[bl][d-1]];
		}
		return ret;
	}
	int bl=bel[l]+1,br=bel[r]-1;
	int L=st[bl],R=ed[br];
	for(int i=l;i<L;++i){
		if(a[i]<d||a[i]>u)continue;
		ret+=0ll
			+m1[bl-1][i-st[bl-1]+1][maxpos[bl-1][a[i]-1]]
			-m1[bl-1][l-st[bl-1]][maxpos[bl-1][a[i]-1]]
			-m1[bl-1][i-st[bl-1]+1][maxpos[bl-1][d-1]]
			+m1[bl-1][l-st[bl-1]][maxpos[bl-1][d-1]];
		ret+=m2[br][u]-m2[bl-1][u]-m2[br][a[i]]+m2[bl-1][a[i]];
	}
	for(int i=R+1;i<=r;++i){
		if(a[i]<d||a[i]>u)continue;
		ret+=0ll
			+m1[br+1][i-R][maxpos[br+1][a[i]-1]]
			-m1[br+1][i-R][maxpos[br+1][d-1]];
		ret+=0ll
			+m1[bl-1][ed[bl-1]-st[bl-1]+1][maxpos[bl-1][a[i]]]
			-m1[bl-1][ed[bl-1]-st[bl-1]+1][maxpos[bl-1][d-1]]
			-m1[bl-1][l-st[bl-1]][maxpos[bl-1][a[i]]]
			+m1[bl-1][l-st[bl-1]][maxpos[bl-1][d-1]];
		ret+=0ll
			+m2[br][a[i]]-m2[bl-1][a[i]]-m2[br][d-1]+m2[bl-1][d-1];
	}
	for(int i=bl;i<=br;++i){
		ret+=0ll
			+m3[i][maxpos[i][u]]
			+m5[i][i-1][maxpos[i][u]]
			-m5[i][bl-1][maxpos[i][u]];
		ret-=0ll
			+m3[i][maxpos[i][d-1]]
			+m5[i][i-1][maxpos[i][d-1]]
			-m5[i][bl-1][maxpos[i][d-1]];
		ret-=1ll
			*(m2[i-1][d-1]-m2[bl-1][d-1])
			*(0ll+m1[i][ed[i]-st[i]+1][maxpos[i][u]]-m1[i][ed[i]-st[i]+1][maxpos[i][d-1]]);
		ret-=0ll
			+m6[i][maxpos[i][d-1]][maxpos[i][u]]-m6[i][maxpos[i][d-1]][maxpos[i][d-1]];
	}
	return ret;
}
int main(){
	n=read(),m=read();
	for(int i=1;i<=n;++i){
		a[i]=read();
	}
	pre();
	for(int i=1;i<=m;++i){
		int l,r,d,u;
		l=read(),r=read(),d=read(),u=read();
		printf("%lld\n",query(l,r,d,u));
	}
} 
2020/8/24 14:00
加载中...