QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#718097#9252. Penguins in Refrigeratoryz_lyWA 4ms89568kbC++143.4kb2024-11-06 19:41:392024-11-06 19:41:43

Judging History

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

  • [2024-11-06 19:41:43]
  • 评测
  • 测评结果:WA
  • 用时:4ms
  • 内存:89568kb
  • [2024-11-06 19:41:39]
  • 提交

answer

#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline int read(){
	int f=1,x=0;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-')
			f=-f;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		x=x*10+ch-'0';
		ch=getchar();
	}
	return f*x;
}
inline void write(int k){
	if(k<0){
		putchar('-');
		k=-k;
	}
	if(k>9)
		write(k/10);
	putchar(k%10+'0');
}
/*
首先将点按照<=w/2和>w/2分成两个集合,记为S和T
发现S中的元素可以随意交换,T中元素相对顺序固定
那么对于一个S中的元素找到左边第一个在T中且不能交换的点和右边第一个不能交换的点,记为(L[i],R[i])
那么i在这个区间中都是合法的,而且发现这些区间一定不相交,只会有包含关系
那么直接建一棵树,从下往上考虑,到达u的时候,u子树中全部放完了,那么u就有siz[u]+R[i]-L[i]-1中放法,方案数就求出来了
对于第二问,连边T中的i->i+1,并且连边L[i]->i->R[i],用优先队列跑拓扑序列就行了
求解L[i],R[i]用st表+二分就行了
*/
const ll mod=1e9+7;
int n,W,p[1000005],w[1000005],num,st[1000005][25],LG[1000005],L[1000005],R[1000005],sm[1000005],cnt,first[1000005],siz[1000005],d[1000005];
ll ans=1;
int query(int l,int r){
	int k=LG[r-l+1];
	return max(st[l][k],st[r-(1<<k)+1][k]);
}
vector<int> q[1000005],g[1000005],G[1000005],ans1;
struct q1{
	int u,v,nex;
}a[2000005];
void add(int u1,int v1){
	a[++cnt]={u1,v1,first[u1]};
	first[u1]=cnt;
}
void dfs(int u){
	siz[u]=1;
	for(int i=first[u];i;i=a[i].nex){
		dfs(a[i].v);
		siz[u]+=siz[a[i].v];
	}
	if(u)
		ans=ans*(siz[u]+sm[R[u]]-sm[L[u]]-1)%mod;
}
bool cmp(int x,int y){
	return R[x]>R[y];
}
int main(){
	n=read();
	W=read();
	for(int i=1;i<=n;i++){
		p[i]=read();
	}
	for(int i=1;i<=n;i++){
		w[i]=read();
	}
	for(int i=1;i<=n;i++){
		st[i][0]=w[p[i]];
	}
	for(int i=2;i<=n;i++){
		LG[i]=LG[i>>1]+1;
	}
	for(int j=1;j<=20;j++){
		for(int i=1;i+(1<<j)-1<=n;i++){
			st[i][j]=max(st[i][j-1],st[i+(1<<(j-1))][j-1]);
		}
	}
	sm[0]=1;
	for(int i=1;i<=n;i++){
		sm[i]=sm[i-1]+(w[p[i]]>W/2);
	}
	sm[n+1]=sm[n]+1;
	for(int i=1;i<=n;i++){
		if(w[p[i]]<=W/2){
			int l=1,r=i;
			while(l<r){
				int mid=(l+r)>>1;
				if(query(mid,i-1)+w[p[i]]>W)
					l=mid+1;
				else
					r=mid;
			}
			q[l-1].emplace_back(i);
			L[i]=l-1;
			l=i+1,r=n+1;
			while(l<r){
				int mid=(l+r)>>1;
				if(query(i+1,mid)+w[p[i]]>W)
					r=mid;
				else
					l=mid+1;
			}
			R[i]=r;
			g[r].emplace_back(i);
			G[L[i]].emplace_back(i);
			G[i].emplace_back(R[i]);
			d[i]++;
			d[R[i]]++;
		}
	}
	for(int i=0;i<=n+1;i++){
		sort(q[i].begin(),q[i].end(),cmp);/*包含*/
	}
	stack<int> s;
	s.emplace(0);
	for(int i=0;i<=n+1;i++){
		for(auto j:g[i]){
			s.pop();
		}
		for(auto j:q[i]){
			add(s.top(),j);
			s.emplace(j);
		}
	}
	dfs(0);
	int las=0;
	for(int i=1;i<=n;i++){
		if(w[p[i]]>W/2){
			G[las].emplace_back(i);
			d[i]++;
			las=i;
		}
	}
	priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > > h;
	for(int i=0;i<=n+1;i++){
		if(!d[i])
			h.emplace(make_pair(p[i],i));
	}
	while(!h.empty()){
		int k=h.top().second;
		h.pop();
		if(k&&k<=n)
			ans1.emplace_back(k);
		for(auto i:G[k]){
			if(!--d[i])
				h.emplace(make_pair(p[i],i));
		}
	}
	write(ans);
	putchar('\n');
	for(auto i:ans1){
		write(p[i]);
		putchar(' ');
	}
	return 0;
}

详细

Test #1:

score: 0
Wrong Answer
time: 4ms
memory: 89568kb

input:

5 10
1 2 3 4 5
6 5 3 9 2

output:

3
1 2 3 4 5 

result:

wrong answer 2nd lines differ - expected: '5 4 2 1 3', found: '1 2 3 4 5 '