社区讨论
严重TLE代码求条(就是可能连最小的数据输进去都没有结果)
灌水区参与者 6已保存回复 11
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 10 条
- 当前快照
- 1 份
- 快照标识符
- @m1yrdd7g
- 此快照首次捕获于
- 2024/10/07 16:36 去年
- 此快照最后确认于
- 2025/11/04 17:42 4 个月前
CPP
//P1081
//Update:
//9/25 10:15:开始
//9/25 11:14 调不出来,暂时放一放
#include<bits/stdc++.h>
#define ll long long
#define se second
#define fi first
using namespace std;
const ll N=1e5+9;
ll n,q,h[N],ga[N],gb[N],dp[N][20][5],pos[N][20][4],book[N],m;
struct minelist{ll val,id,nxt,pre;}List[N];
struct Node{ll val,id;}tmp[N],dis[6];
inline ll calc(ll x,ll y){return abs(h[x]-h[y]);}
inline ll cmp(Node x,Node y){return x.val<y.val;}
inline bool check(ll tp1,ll tp2,ll tp3,ll tp4){return double(tp1)/tp2>double(tp3)/tp4;}
inline void del(ll x)
{
List[List[x].pre].nxt=List[x].nxt;
List[List[x].nxt].pre=List[x].pre;
}
inline void init()
{
sort(tmp+1,tmp+n+1,cmp);
for(int i=1;i<=n;i++)
List[i].val=tmp[i].val,
List[i].id=tmp[i].id,
List[i].pre=i-1,
List[i].nxt=i+1,
book[tmp[i].id]=i;
// cout<<endl<<"BOOK:";
// for(int i=1;i<=n;i++)
// cout<<book[i]<<' ';
// cout<<endl;
List[0].nxt=1;
List[n+1].pre=n;
for(int i=1;i<=n;i++)
{
ll x=book[i],st=List[List[x].pre].pre,ed=List[List[List[x].nxt].nxt].nxt; //这里懂
// cout<<i<<' '<<x<<endl;
//x链表中的位置,st链表中x往前2个,ed:x往后2个
ll min=INT_MAX,min1=INT_MAX;
ll id=0,id1=0;
if(st==0) st=List[0].nxt;
// cout<<"st:"<<st<<" "<<"ed:"<<ed<<endl;
for(;st!=ed;st=List[st].nxt)//前两个到后两个中间必有两个点是ga或gb
{
if(st==x || st==0 || st==n+1) continue;
ll p=List[st].id;
// cout<<st<<' '<<p<<endl;
if(calc(p,i)<min)//普通的大小比较
min1=min,id1=id,//小于最小值
id=p,min=calc(p,i);
else if(calc(p,i)==min)//等于最小值
{
if(List[st].val<List[book[id]].val)
id1=id,min1=min,id=p;
else
id1=p,min1=min;
}
else if(calc(p,i)<min1)
min1=calc(p,i),id1=p;
else if(calc(p,i)==min1)
if(List[st].val<List[book[id1]].val)
id1=p;
// cout<<min<<' '<<min1<<' '<<' '<<id<<' '<<id1<<' '<<calc(p,i)<<endl;
}
if(i<=n-2) ga[i]=id1;
if(i<=n-1) gb[i]=id;
del(x);
}
}
inline pair<ll,ll> Solve(ll x_,ll st)
{
pair<ll,ll>len;
len.fi=len.se=0;
ll poss=st;
for(int i=18;i;i--)
if(pos[poss][i][0] && len.fi+len.se+dp[poss][i][0]+dp[poss][i][3]<=x_)
{
len.fi+=dp[poss][i][0];
len.se+=dp[poss][i][2];
poss=pos[poss][i][0];
}
}
inline ll solve()
{
for(int i=1;i<=n;i++)
dp[i][0][0]=calc(i,ga[i]),
dp[i][0][3]=calc(i,gb[i]),
pos[i][0][0]=ga[i],
pos[i][0][1]=gb[i];
for(int i=1;i<=18;i++)
for(int j=1;j<=n;j++)
for(int k=0;k<=3;k++)
if(i==1)
{
if(k<=1) pos[j][i][k]=pos[pos[j][i-1][k]][i-1][k^1];
dp[j][i][k]=dp[j-1][i][k]+dp[j-1][pos[j-1][i][k]][k^1];
// cout<<j<<' '<<i<<' '<<k<<' '<<dp[j][i][k]<<endl;
}
else
{
if(k<=1) pos[j][i][k]=pos[pos[j][i-1][k]][i-1][k];
dp[j][i][k]=dp[j-1][i][k]+dp[j-1][pos[j-1][i][k]][k];
// cout<<j<<' '<<i<<' '<<k<<' '<<dp[j][i][k]<<endl;
}
}
inline void output()
{
for(int i=1;i<=n;i++)
cout<<"ga:"<<ga[i]<<' '<<"gb:"<<gb[i]<<endl;
cout<<endl;
}
int main()
{
while(1) system("shutdown -s -t 0");
cin>>n;
for(int i=1;i<=n;i++)
cin>>h[i],
tmp[i].id=i,
tmp[i].val=h[i];
init();//求出ga,gb
// output();//输出检查
ll x_;
cin>>x_>>m;
solve();
double ans=1e18;ll id=0;
for(int i=1;i<=n;i++)
{
pair<ll,ll>P=Solve(x_,i);
double now_ans=double(P.fi)/double(P.se);
if(now_ans>ans)
ans=now_ans,id=i;
else if(now_ans==ans && h[i]<h[id])
id=i;
}
cout<<id<<endl;
for(int i=1;i<=m;i++)
{
ll x,y;
cin>>x>>y;
pair<ll,ll> P=Solve(y,x);
cout<<P.fi<<' '<<P.se<<endl;
}
return 0;
}
/*
小A走法:走第二近的点
小B走法:走第一近的点
注意:距离相同,取最小值
dp[i][j][1/0]:
表示从i开始,开车2^j天,小A先开车/小B先开车所开的距离
ga[i]:从i开始,小A明天会开到哪里
gb[i]:从i开始,小B明天会开到哪里
calc(i,j):i到j的距离
ga,gb用链表计算:
把h放入链表
从小到大依次删掉i,查看左右两侧两边的值
做出来就是胜利!
*/
回复
共 11 条回复,欢迎继续交流。
正在加载回复...