一本通1755:星际探测

链接

\(k\) 很小,建一个线段树,\(O(k^2)\) 合并。
询问时查找区间最小值的位置,合并去掉最小值的左右两段区间。

#include<bits/stdc++.h>
#define IL inline
#define ls k<<1
#define rs k<<1|1
#define LL unsigned int
using namespace std;
const int N=1e5+3;
LL n,m,fac[10];
struct kk{
	LL d,v;
	bool operator<(const kk &a) const{
	return d<a.d;}
}a[N];
struct hh{
	 LL f[7]={1};
	 void clear(){memset(f,0,sizeof(f)),f[0]=1;}
};
hh operator+(const hh &a,const hh &b){
	hh c;c.clear();
	for(int i=1;i<=6;++i)
	  for(int j=0;j<=i;++j)
	    c.f[i]+=a.f[j]*b.f[i-j];
	return c;
}
IL int in(){
	char c;int f=1;
	while((c=getchar())<'0'||c>'9')
	  if(c=='-') f=-1;
	int x=c-'0';
	while((c=getchar())>='0'&&c<='9')
	  x=x*10+c-'0';
	return x*f;
} 
struct segment{
	int Min[N<<2],pos[N<<2];
	hh f[N<<2];
	IL void pushup(int k){
		if(Min[ls]<Min[rs]) Min[k]=Min[ls],pos[k]=pos[ls];
		else Min[k]=Min[rs],pos[k]=pos[rs];
		f[k]=f[ls]+f[rs];
	}
	void build(int k,int l,int r){
		if(l==r){Min[k]=a[l].v,pos[k]=l,f[k].f[1]=a[l].v;return;}
		int mid=l+r>>1;
		build(ls,l,mid),build(rs,mid+1,r);
		pushup(k);
	}
	int ask1(int k,int l,int r,int ll,int rr){
		if(l>=ll&&r<=rr) return pos[k];
		int mid=l+r>>1;
		if(rr<=mid) return ask1(ls,l,mid,ll,rr);
		if(ll>mid) return ask1(rs,mid+1,r,ll,rr);
		int lc=ask1(ls,l,mid,ll,rr),rc=ask1(rs,mid+1,r,ll,rr);
		return a[lc].v<a[rc].v?lc:rc;
	}
	hh ask2(int k,int l,int r,int ll,int rr){
		if(l>=ll&&r<=rr) return f[k];
		int mid=l+r>>1;
		hh lc,rc;lc.clear(),rc.clear();
		if(ll<=mid) lc=ask2(ls,l,mid,ll,rr);
		if(rr>mid) rc=ask2(rs,mid+1,r,ll,rr);
		return lc+rc;
	}
	hh query(int l,int r,int k){
		int pos=ask1(1,1,n,l,r);
		hh lc,rc;lc.clear(),rc.clear();
		if(l<=pos-1) lc=ask2(1,1,n,l,pos-1);
		if(pos+1<=r) rc=ask2(1,1,n,pos+1,r);
		return lc+rc;
	}
}T;
int main()
{
	int l,r,k;
	n=in(),m=in();
	fac[0]=1;for(int i=1;i<=6;++i) fac[i]=fac[i-1]*i;
	for(int i=1;i<=n;++i) a[i].d=in();
	for(int i=1;i<=n;++i) a[i].v=in();
	sort(a+1,a+n+1);
	T.build(1,1,n);
	for(int i=1;i<=m;++i){
		l=in(),r=in(),k=in();
		l=lower_bound(a+1,a+n+1,(kk){l,0})-a,
		r=upper_bound(a+1,a+n+1,(kk){r,0})-a-1;
		if(l>r){printf("0\n");continue;}
		hh ans=T.query(l,r,k);
		printf("%u\n",ans.f[k]*fac[k]);
	}
	return 0;
}
posted @ 2020-11-02 16:10  (o-ωq)).oO  阅读(115)  评论(0编辑  收藏  举报