QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#718097 | #9252. Penguins in Refrigerator | yz_ly | WA | 4ms | 89568kb | C++14 | 3.4kb | 2024-11-06 19:41:39 | 2024-11-06 19:41:43 |
Judging History
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 '