QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#51502#1443. Potato ShuffleJayfeather233WA 2ms3856kbC++4.0kb2022-10-02 15:41:002022-10-02 15:41:04

Judging History

你现在查看的是最新测评结果

  • [2023-08-10 23:21:45]
  • System Update: QOJ starts to keep a history of the judgings of all the submissions.
  • [2022-10-02 15:41:04]
  • 评测
  • 测评结果:WA
  • 用时:2ms
  • 内存:3856kb
  • [2022-10-02 15:41:00]
  • 提交

answer

#include <iostream>
#include <cstdio>
#include <algorithm>
const int MOD = 1e9+7;
int fast_pow(int a,int b){
	int ans=1;
	while(b){
		if(b&1) ans=(1ll*ans*a)%MOD;
		a=(1ll*a*a)%MOD;
		b>>=1;
	}
	return ans;
}
#define ls (u<<1)
#define rs ((u<<1)+1)
#define MAXN 100100
namespace maxtree{
	int maxn[MAXN<<2];
	void build(int* s, int u, int l, int r){
		if(l==r){
			maxn[u]=s[l];
			return;
		}
		int mid=(l+r)>>1;
		build(s,ls,l,mid);
		build(s,rs,mid+1,r);
		maxn[u]=std::max(maxn[ls],maxn[rs]);
	}
	int ask(int u, int l, int r, int ll, int rr){
		if(ll<=l&&r<=rr) return maxn[u];
		if(rr<l || r<ll) return 0;
		int mid=(l+r)>>1;
		return std::max(ask(ls,l,mid,ll,rr),ask(rs,mid+1,r,ll,rr));
	}
}
namespace sizetree{
	int sz[MAXN<<2];
	void build(int u, int l, int r){
		if(l==r){
			sz[u]=1;
			return;
		}
		int mid=(l+r)>>1;
		build(ls,l,mid);
		build(rs,mid+1,r);
		sz[u]=sz[ls]+sz[rs];
	}
	int ask(int u, int l, int r, int ll, int rr){
		if(ll<=l&&r<=rr) return sz[u];
		if(rr<l || r<ll) return 0;
		int mid=(l+r)>>1;
		return ask(ls,l,mid,ll,rr)+ask(rs,mid+1,r,ll,rr);
	}
	void modify(int u,int l,int r,int x){
		//printf("mdy at %d %d %d %d\n",u,l,r,x);
		if(x<l || r<x) return;
		if(l==r){
			sz[u]=0;
			return;
		}
		int mid=(l+r)>>1;
		modify(ls,l,mid,x);
		modify(rs,mid+1,r,x);
		sz[u]=sz[ls]+sz[rs];
	}
	void opt(int u,int l,int r){
		printf("%d: %d %d %d\n",u,l,r,sz[u]);
		if(l==r) return;
		int mid=(l+r)>>1;
		opt(ls,l,mid);
		opt(rs,mid+1,r);
	}
}
#undef ls
#undef rs
namespace link{
	struct point{
		int pos,nxt,pre;
	}s[MAXN];
	int head[MAXN],ls=1;
	void add(int u,int p){//add a integer[u] at position[p]
		s[ls].pos=p;
		s[ls].nxt=head[u];
		s[head[u]].pre=ls;
		head[u]=ls++;
	}//reverse
}
using namespace std;
int n,k;
int disc_mp[100100];
int ny[100100];
int after_disc[100100];
int find_next_max(int l,int r){
	return maxtree::ask(1,1,n,l,r);
}
int C(int n,int m){//choose m from tot n
	int ans=1;
	for(int i=1;i<=m;i++){
		ans=(1ll*ans*ny[i])%MOD;
		ans=(1ll*ans*(n-i+1))%MOD;
	}
	return ans;
}
int tot;
int work(int l,int r,int minn){
	int maxn=find_next_max(l,r);
	//if(maxn-k<minn) return 1;
	if(maxn<minn || r<=l) return 1;
	//printf("AT %d %d %d %d\n",l,r,maxn,minn);
	int tot_sz=sizetree::ask(1,1,n,l,r);
	int bel=0;
	for(int t=minn;disc_mp[t]<=k-disc_mp[maxn]&&t<=tot;t++){
		//printf(" disc:t=%d\n",t);
		for(int i=link::head[t];i;i=link::s[i].nxt){
			if(r<link::s[i].pos) break;
			if(link::s[i].pos<l) continue;
			bel++;
			if(!link::s[i].pre){
				link::head[t]=link::s[i].nxt;
				link::s[link::s[i].nxt].pre=0;
			}else{
				link::s[link::s[i].pre].nxt=link::s[i].nxt;
				link::s[link::s[i].nxt].pre=link::s[i].pre;
			}
			sizetree::modify(1,1,n,link::s[i].pos);
			//sizetree::opt(1,1,n);
			//printf(" modify:%d\n",link::s[i].pos);
		}
		minn=max(minn,t);
	}
	//printf("  size:%d bel:%d\n",tot_sz,bel);
	int ans=C(tot_sz,bel);
	for(int i=link::head[maxn];i;i=link::s[i].nxt){
		ans=(1ll*ans*work(l,link::s[i].pos-1,minn+1))%MOD;
		l=link::s[i].pos+1;
	}
	ans=(1ll*ans*work(l,r,minn+1))%MOD;
	return ans;
}
struct tt{
	int v,pos;
}disc[100100];
int operator < (const tt a,const tt b){
	return a.v==b.v ? a.pos>b.pos : a.v<b.v;
}
int main(){
	cin>>n>>k;
	for(int i=1;i<=n;i++) ny[i]=fast_pow(i,MOD-2);
	for(int i=0;i<n;i++){
		scanf("%d",&disc[i].v);
		disc[i].pos=i;
	}
	sort(disc,disc+n);
	for(int i=1;i<n;i++){
		if(disc[i].v!=disc[i-1].v){
			disc_mp[tot]=disc[i-1].v;
			disc[i-1].v=tot;
			tot++;
		}else{
			disc_mp[tot]=disc[i-1].v;
			disc[i-1].v=tot;
		}
	}
	disc_mp[tot]=disc[n-1].v;
	disc[n-1].v=tot;
	//for(int i=0;i<=tot;i++) printf("mp:%d->%d\n",i,disc_mp[i]);
	for(int i=0;i<n;i++){
		after_disc[disc[i].pos+1]=disc[i].v;
	}
	//for(int i=1;i<=n;i++){
	//	printf("%d ",after_disc[i]);
	//}
	//printf("\n");
	maxtree::build(after_disc,1,1,n);
	sizetree::build(1,1,n);
	for(int i=n;i>=1;i--){
		link::add(after_disc[i],i);
	}
	printf("%d",work(1,n,0));
	return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 2ms
memory: 3744kb

input:

3 7
5 2 4

output:

3

result:

ok "3"

Test #2:

score: 0
Accepted
time: 2ms
memory: 3856kb

input:

5 4
1 2 3 2 1

output:

10

result:

ok "10"

Test #3:

score: 0
Accepted
time: 2ms
memory: 3680kb

input:

6 4
9 10 1 9 8 9

output:

1

result:

ok "1"

Test #4:

score: 0
Accepted
time: 2ms
memory: 3828kb

input:

8 0
4 9 2 9 2 3 9 10

output:

1

result:

ok "1"

Test #5:

score: 0
Accepted
time: 2ms
memory: 3748kb

input:

5 3
9 8 1 9 8

output:

1

result:

ok "1"

Test #6:

score: -100
Wrong Answer
time: 2ms
memory: 3808kb

input:

6 12
4 7 2 9 1 9

output:

30

result:

wrong answer 1st words differ - expected: '60', found: '30'