QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#717755 | #9252. Penguins in Refrigerator | Hkueen | WA | 0ms | 20120kb | C++14 | 3.7kb | 2024-11-06 18:53:13 | 2024-11-06 18:53:16 |
Judging History
answer
/*
这种题
我当然是不会做的
哇,这个思路可以啊
考虑把这n个元素分到两个集合S,T中,其中S={i|w[i]<=W/2},T={i|w[i]>W/2}
那么S中的元素互相可以随便交换,T中的元素相对顺序则无法改变
我们可以对每个S中的元素i求出一个L[i]和一个R[i],分别表示i左右第一个满足w[i]+w[j]>W的j(显然j∈T)
稍微想想可以发现,每对[L,R]要么包含,要么不交,因此形成一个树形结构
拟造一个初始序列,里面只包含所有T中的元素
那么我们对于每棵树,从底到根地插入i,当插入i时,算出(L[i],R[i]])现在已经插入了多少个元素(在T中的也算),i可以在任选一个位置插进去
所以这里对方案数的贡献是乘上 元素个数+1
这样可以算出第一问
第二问非常简单,对于每个T中的元素,按照原顺序连边(T[i],T[i+1])
对于每个S中的元素,连边(L[i],i),(i,R[i])
跑最小拓扑序即可
我靠要离散化
6,没看到
*/
#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline int re(){
int x=0,c=getchar();
while(c<48||c>57)c=getchar();
while(c>47&&c<58)x=(x<<3)+(x<<1)+(c&15),c=getchar();
return x;
}
void wr(int x){
if(x>9)wr(x/10);
putchar(x%10|48);
}
constexpr int mod=1e9+7,N=5e6+10;
int tr[N],W,fl,n,tot;
int lowbit(int x){return x&-x;}
void ad(int x,int v){
if(fl<2)x=tot-x+1;
//fprintf(stderr,"ad(%d,%d)\n",x,v);
if(!fl)for(int i=x;i<=tot;i+=lowbit(i))tr[i]=max(tr[i],v);
else if(fl==1)for(int i=x;i<=tot;i+=lowbit(i))tr[i]=min(tr[i],v);
else for(int i=x;i<=n;i+=lowbit(i))tr[i]+=v;
}
int su(int x){
if(fl<2)x=tot-x+1;
//fprintf(stderr,"su(%d)\n",x);
int res;
if(!fl){
res=0;
for(int i=x;i;i-=lowbit(i))res=max(res,tr[i]);
}
else if(fl==1){
res=n+1;
for(int i=x;i;i-=lowbit(i))res=min(res,tr[i]);
}
else{
res=0;
for(int i=x;i;i-=lowbit(i))res+=tr[i];
}
return res;
}
ll ans;
int i,p[N],w[N],las;
bool ins[N];
int first[N],cnt;
struct Edge{
int u,v,nex;
}a[N<<1];
int d[N];
void add(int u,int v){
//printf("%d %d\n",u,v);
a[++cnt]={u,v,first[u]};
first[u]=cnt;
++d[v];
}
int L[N],R[N],qzh[N],tmp[N];
priority_queue<pair<int,int> >q;
int ls(int x){return lower_bound(tmp+1,tmp+1+tot,x)-tmp;}
int main(){
n=re(),W=re();
for(i=1;i<=n;++i)p[i]=re();
for(i=1;i<=n;++i)tmp[i]=re();
for(i=1;i<=n;++i)w[i]=tmp[p[i]];
//for(i=1;i<=n;++i)printf("%d ",p[i]);putchar(10);
//for(i=1;i<=n;++i)printf("%d ",w[i]);putchar(10);
for(i=1;i<=n;++i){
qzh[i]=qzh[i-1]+1;
if(w[i]<=(W>>1))ins[i]=1,--qzh[i];
else if(las)add(las,i),las=i;
else las=i;
tmp[++tot]=w[i],tmp[++tot]=W-w[i]+1;
}
sort(tmp+1,tmp+tot+1);
tot=unique(tmp+1,tmp+tot+1)-tmp-1;
for(i=1;i<=n;++i){
if(ins[i]){
L[i]=su(ls(W-w[i]+1));
if(L[i])add(L[i],i);
}
else ad(ls(w[i]),i);
}
for(i=fl=1;i<=tot;++i)tr[i]=n+1;
for(i=n;i;--i){
if(ins[i]){
R[i]=su(ls(W-w[i]+1));
if(R[i]<=n)add(i,R[i]);
}
else ad(ls(w[i]),i);
}
//for(i=1;i<=n;++i)printf("L[%d]=%d R[%d]=%d\n",i,L[i],i,R[i]);
//return 0;
fl=2;
for(i=1;i<=tot;++i)tr[i]=0;
for(i=1;i<=n;++i)if(ins[i])q.push({-(R[i]-L[i]),i});
ans=1;
while(!q.empty()){
int u=q.top().second;q.pop();
ad(L[u]+1,1);
ans=ans*(qzh[R[u]-1]-qzh[L[u]]+su(R[u]-1)-su(L[u]))%mod;
//printf("%lld ",ans);
//printf("u=%d %d %d ans*=(%d-%d+%d-%d)\n",u,L[u],R[u]-1,qzh[R[u]-1],qzh[L[u]],su(R[u]-1),su(L[u]));
}
printf("%lld\n",ans);
for(i=1;i<=n;++i)if(!d[i])q.push({-p[i],i});
while(!q.empty()){
wr(-q.top().first),putchar(32);
int u=q.top().second;q.pop();
for(int i=first[u];i;i=a[i].nex){
int v=a[i].v;
if(!--d[v])q.push({-p[v],v});
}
}
return 0;
}
详细
Test #1:
score: 0
Wrong Answer
time: 0ms
memory: 20120kb
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 '