首页 > 其他分享 >RQNOJ 658(观光公交)

RQNOJ 658(观光公交)

时间:2022-10-25 12:01:14浏览次数:41  
标签:head cout int 观光 tot RQNOJ now 658 wait


几大注意点:

1.一次使用氦气加速器会把后面分成好几段。

2.我们仅维护end[i],wait[i]恒定,因此需提前让wait[i]=max(wait[i-1],wait[i]);

3.w[i]+w[i+1]+...+w[j],且w恒定,故可预处理sum[i](满足累加性)


#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<string>
#include<algorithm>
#include<queue>
#include<functional>
#include<iostream>
#define MAXN 1000 +10
#define MAXM 10000 + 10
#define MAXK 100000 + 10
#define MAXD 100 + 10
#define MAXT 100000 + 10
using namespace std;
struct man
{
int t,l,r;
}t[MAXM];
struct interval
{
int l,r,w;
};

int n,m,k,ans,d[MAXN+1],wait[MAXN+1],w[MAXN+1],end[MAXN+1],sum[MAXN+1];
bool operator<(const interval a,const interval b) //重载 operator < 的意思 为q做准备
{


return a.w<b.w;
}

priority_queue<interval> q; //priority_queue<Node, vector<Node>, greater<Node> >; 完整的不能用


void push(int l,int r)
{
bool flag=0;
for (int i=l;i<r;i++) if (d[i]) {flag=1;break;}
if (!flag) return;
int tot=sum[r]-sum[l];
if (!tot) return ;
interval now;
now.w=tot;
now.l=l;
now.r=r;
q.push(now);

// cout <<"add "<< now.l << ' ' << now.r <<' '<< now.w << endl;
}

int main()
{
// freopen("qc.in","r",stdin);
memset(wait,0,sizeof(wait));
memset(w,0,sizeof(w));

scanf("%d%d%d",&n,&m,&k);
for (int i=1;i<=n-1;i++)
scanf("%d",&d[i]);
for (int i=1;i<=m;i++)
{
scanf("%d%d%d",&t[i].t,&t[i].l,&t[i].r);
wait[t[i].l]=max(wait[t[i].l],t[i].t);
w[t[i].r]++;
}
end[1]=0;
for (int i=2;i<=n;i++)
end[i]=max(end[i-1],wait[i-1])+d[i-1];
ans=0;
for (int i=1;i<=m;i++)
ans+=end[t[i].r]-t[i].t;

sum[1]=sum[0]=0;
for (int i=2;i<=n;i++) {sum[i]=sum[i-1]+w[i]; wait[i]=max(wait[i-1],wait[i]);}

// for (int i=0;i<=n;i++) cout<<end[i]<<' ';
// cout<<endl;


int tot=d[1],head=1;
for (int i=2;i<=n;i++)
{
if (wait[i]>=end[i])
{
if (tot) push(head,i);
tot=0;
head=i;
}
tot+=d[i];
/*
tot+=w[i]*min(1,d[i]);
// tot+=w[i];
*/
}


if (tot) push(head,n);


//00 cout<<ans<<endl;
//贪心
// sort(t+1,t+m+1,cmp);

// 调试
/* while( !q.empty() ){
cout << q.top().l << ' ' << q.top().r <<' '<< q.top().w << endl;
q.pop();
}
*/
/*
for (int i=1;i<=n;i++)
{
cout<<end[i]<<' ';
}
*/
while (k&&!q.empty())
{
/* cout<<"/"<<endl;
for (int i=1;i<=n;i++)
{
cout<<end[i]<<' ';
}
cout<<endl;
for (int i=1;i<=n;i++)
{
cout<<wait[i]<<' ';
}

cout<<endl;
*/
interval now=q.top();
q.pop();
ans-=now.w;
int i=now.l;
//000
// cout << now.l << ' ' << now.r <<' '<< now.w << endl;
// cout << ans << endl;
//000


while (!d[i]) i++;
d[i]--;
int head=i,tot=0,i2=0;
i++;
while (i<=now.r/*&&wait[i]<end[i]*/)
{
// tot+=w[i-1];
end[i]--;
//000
// for (int cse=1;cse<=n;cse++) cout<<end[cse]<<',';
// cout<<endl;
//-
// cout<<i<<endl;
// cout<<wait[i+1]<<' '<<end[i+1]<<endl;
if (wait[i]==end[i])
{push(head,i);head=i;}
i++;
}

i--;
if (head!=now.r) push(head,now.r);

/*
if (i>now.r) {cout<<"smile"<<endl;
cout<<'<'<<' '<<i<<' '<<wait[i]<<' '<<end[i]<<' '<<endl;}
*/
// cout<<"i2:"<<i2<<endl;
/* if (i2) i=i2;
i--;
push(head,i);
if (i<now.r)
{
// if (!d[head]) tot+=w[head];
push(i,now.r);
}
*/

//处理 end[i] 显然最多影响到 now.r
k--;
}

cout<<ans<<'\n';


// 调试
/*
while( !q.empty() ){
cout << q.top().l << ' ' << q.top().r <<' '<< q.top().w << endl;
q.pop();
}
for (int i=1;i<=n;i++)
{
cout<<end[i]<<' ';
}



*/


// while (1);

}



标签:head,cout,int,观光,tot,RQNOJ,now,658,wait
From: https://blog.51cto.com/u_15724837/5794423

相关文章

  • RQNOJ 698(矩形计数-圆内接矩形数)
    查看题目ShowProblem题目:矩形计数问题编号:698题目描述给出圆周上的N个点,请你计算出以这些点中的任意四个为四个角,能构成多少个矩形。点的坐标是这样描述的,给定一......
  • P5658 [CSP-S2019] 括号树
    P5658CSP-S2019括号树先考虑线性的情况.....(....)如果是(则将其左边的答案加入栈,这个点的答案为0如果是)则将栈顶左边的答案+1作为贡献(答案)每个点的答案为以这个......
  • P5658 CSP-S2019括号树
    [CSP-S2019]括号树(傻逼绿题题目背景本题中合法括号串的定义如下:()是合法括号串。如果A是合法括号串,则(A)是合法括号串。如果A,B是合法括号串,则AB是合法括......
  • 658. 找到 K 个最接近的元素
    658.找到K个最接近的元素给定一个排序好的数组 arr,两个整数k和x,从数组中找到最靠近x(两数之差最小)的k个数。返回的结果必须要是按升序排好的。整数a比......