Codeforces Round #433 (Div. 2) 总结

来源:互联网 发布:内容运营优化 编辑:程序博客网 时间:2024/06/14 03:18

这场么…又一次打炸掉了..(不知道为啥这场他们的手速都这么快,我在1:47用一个保证fst的算法过了D题pp结果也才400名)..最后加上D题fst…排名可想而知。(惨啊!qwq)
最终排名:rank813,rating-=41,目前rating:1764(好像这几场下来离紫名越来越远了啊有木有…)
P.S. 这场打完我还有一个教训…虽然打前两题手速要快,但是..太快就会GG啊。。

A. Fraction

题意:给你一个正整数n,问你能求得的最大的真分数且是既约分数且分子与分母的和为n的分数是多少,输出分子和分母。
思路&&题解:这一题我一上来看了1分30时我就打完了,然后交上去WA掉了..白白少了50分。最后再仔细看一遍题,发现我没有看到既约分数..最后加个GCD判一下就好了..

代码如下:

#include<bits/stdc++.h>using namespace std;long long n;inline int gcd(int a,int b) {    return b?gcd(b,a%b):a;}int main() {    cin>>n;    if(n%2==0) {        int a=n/2-1,b=n/2+1;        while(gcd(a,b)!=1) {            a--;            b++;        }        cout<<a<<" "<<b<<endl;    }    else {        int a=n/2,b=n/2+1;        while(gcd(a,b)!=1) {            a--;            b++;        }        cout<<a<<" "<<b<<endl;    }    return 0;} 

B. Maxim Buys an Apartment

题意: Maxim想在一条街上买一幢公寓,这条街上有n幢公寓标号从左到右为1~n,Maxim定义一幢公寓为“好”的,只要和它相邻的公寓中至少有一幢已经有人住了。现在Maxim知道其中有k幢已经被人买走了且有人住了,但他不知道现在住了人的公寓的标号是多少,现在让你求最少有多少公寓是“好”的和最多有多少公寓是“好”的。
思路&&题解:首先,显然的是当k==n或k==0的时候,答案一定是0 0(显然)。否则最少的情况一定是k幢公寓从编号1开始是连着被买的,这样只有一幢公寓是好的。现在我们考虑最大多少幢,我们可以发现就从编号2开始每隔两个放一个,(即2,5,8….)(可以证明这是最优的),那么答案就是min(n-k,2*k)..我刚开始没特判k==0 WA了..还有一次瞎写了个算法GG了..

代码如下:

#include<bits/stdc++.h>using namespace std;long long n,k;int main() {    cin>>n>>k;    if(n==k||k==0) {        cout<<"0 0"<<endl;        return 0;    }    cout<<"1 ";    if(k<=n/3)        cout<<k*2<<endl;    else        cout<<min(n-k,k*2)<<endl;    return 0;}

C. Planning

题意:飞机场原定计划从第一分钟开始每分钟起飞一架飞机,但是由于某些原因导致前k分钟无法起飞飞机。给出每架飞机每延误一分钟的损失costi,问所有飞机都起飞后的最小损失为多少。
思路&&题解:这题只要贪心一下就好了。用一个堆(其实优先队列就行了233)..然后根据cost排列,一个一个赋值下去就行了2333..(其实挺好写的)

代码如下:

#include<bits/stdc++.h>using namespace std;typedef long long ll;const int maxn=300050;ll n,k;struct node{    ll num;    int id;    bool operator < (const node &rhs) const {        return num<rhs.num;    }};priority_queue<node> a;ll ans[maxn];ll sum=0,x[maxn];bool vis[maxn<<1];int main() {    ios::sync_with_stdio(false);    cin.tie(0);    cout.tie(0);    cin>>n>>k;    for(int i=1;i<=n;i++) {        cin>>x[i];        if(i<=k+1)            a.push((node){x[i],i});    }    for(int pos=k+1;pos<=k+n;pos++) {        node now=a.top();        a.pop();        ans[now.id]=pos;        sum+=now.num*(pos-now.id);        if(pos<n)            a.push((node){x[pos+1],pos+1});    }    cout<<sum<<endl;    for(int i=1;i<=n;i++)        cout<<ans[i]<<" ";    cout<<endl;    return 0;}

D. Jury Meeting

题解:给你m个航班,然后使得n个特派员在0号城市开会,最少要让这n个特派员一起在这里待上k天,然后每个航班的航线、时间和花费已知,问你满足题意的最小花费。如果不满足,则输出-1。
思路&&题解:这题看起来有点难..实际上想通了挺简单的。只是当时我来不及打了,然后随便瞎糊了个暴力,没想到过pp了,(虽然最后不用想也知道肯定fst..qwq)。实际上这题就是贪心。只要将航班按时间排序,然后从前往后维护出发航班前缀最小值,然后从后往前维护返回航班的后缀最小值,最后枚举一下从哪天开始n个特派员都在0号城市就行了。

代码如下:

#include<bits/stdc++.h>using namespace std;typedef long long ll;const int maxn=200050;struct Edge{    ll d,from,to,val;}a[maxn];ll n,m,k,sum,tot,vis[maxn],l[maxn],r[maxn],ans=1e18;inline ll cmp(Edge a,Edge b) {    return a.d<b.d;}inline void fastIO() {    ios::sync_with_stdio(false);    cin.tie(0);    cout.tie(0);} inline void init() {    memset(vis,0,sizeof vis);    memset(l,-1,sizeof l);    memset(r,-1,sizeof r);}int main() {    fastIO();    cin>>n>>m>>k;    init();    for(int i=1;i<=m;i++)        cin>>a[i].d>>a[i].from>>a[i].to>>a[i].val;    sort(a+1,a+m+1,cmp);    sum=tot=0;    for(int i=1;i<=m;i++) {//      cout<<i<<" "<<sum<<" "<<tot<<endl;        if(a[i].from==0)            continue;        if(vis[a[i].from]==0) {            vis[a[i].from]=a[i].val;            sum+=a[i].val;            tot++;        }        else {            if(vis[a[i].from]>a[i].val) {                sum-=vis[a[i].from];                vis[a[i].from]=a[i].val;                sum+=a[i].val;            }        }        if(tot==n)            l[i]=sum;    }    sum=tot=0;    memset(vis,0,sizeof vis);    for(int i=m;i>=1;i--) {        if(a[i].to==0)            continue;        if(vis[a[i].to]==0) {            sum+=a[i].val;            tot++;            vis[a[i].to]=a[i].val;        }        else {            if(vis[a[i].to]>a[i].val) {                sum-=vis[a[i].to];                sum+=a[i].val;                vis[a[i].to]=a[i].val;            }        }        if(tot==n)            r[i]=sum;    }    for(int i=m;i>=1;i--) {        if(r[i]==-1)            continue;        else {            if(r[i+1]==-1)                continue;            r[i]=min(r[i],r[i+1]);        }    }    for(int i=1;i<=m;i++) {//      cout<<i<<" "<<l[i]<<endl;        if(l[i]==-1)            continue;        int pos=-1,lim=a[i].d+k+1,lef=i+1,rig=m,mid;        while(lef<=rig) {            mid=(lef+rig)>>1;            if(a[mid].d>=lim) {                rig=mid-1;                pos=mid;            }            else                lef=mid+1;        }        if(pos==-1)            continue;        else if(r[pos]!=-1)            ans=min(ans,r[pos]+l[i]);    }    cout<<(ans==1e18?-1:ans)<<endl;    return 0;}

E. Boredom

题意:一个n*n的网格图,有n个标记,每列只有一个标记,定义美丽的矩形为以两个标记所在位置构成的矩形(对角线的两个角)。q次询问,每次询问给你一个矩形,问有多少个美丽的矩形与该矩形相交。
思路&&题解:这题可以用树状数组+离线回答做。首先我们可以知道,如果一个区域内有n个标记,那么这n个标记可以组成n*(n-1)/2个矩形。我们可以将大矩形根据询问的范围将它分成九块,用一维树状数组维护四个角的点数,然后将询问先从左到右排序一遍,更新答案;然后将询问从右到左排序一遍继续更新答案,最后再弄一下就好了(详情请见代码)

代码如下:

#include<bits/stdc++.h>using namespace std;typedef long long ll;const int maxn=200050;int n,m,l,d,u,r,a[maxn];ll ans[maxn];struct treearray {    ll val[maxn];    inline int lowbit(int x){return x&(-x);};    inline void clear(){memset(val,0,sizeof val);}    inline void add(int x){for(int i=x;i<=n;i+=lowbit(i))val[i]++;}    inline ll query(int x){ll res=0;for(int i=x;i>=1;i-=lowbit(i))res+=val[i];return res;}}tx,ty;struct que {    int l,d,r,u,id;    que(int l=0,int d=0,int r=0,int u=0,int id=0):l(l),d(d),r(r),u(u),id(id){}}re[maxn];inline bool cmP(que a,que b){return a.l<b.l;}inline bool Cmp(que a,que b){return a.r>b.r;}inline ll f(ll x){return 1LL*(x-1)*x/2LL;}inline void fastIO(){ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);}int main() {    fastIO();    cin>>n>>m;    for(int i=1;i<=n;i++)cin>>a[i];    for(int i=1;i<=m;i++)cin>>l>>d>>r>>u,re[i]=que(l,d,r,u,i);    sort(re+1,re+m+1,cmP);    int pos=1;    for(int i=1;i<=n&&pos<=m;i++) {        while(re[pos].l==i&&pos<=m)ans[re[pos].id]+=f(tx.query(re[pos].d-1))+f(ty.query(n-re[pos].u)),pos++;        tx.add(a[i]),ty.add(n-a[i]+1);    }    tx.clear(),ty.clear();    sort(re+1,re+m+1,Cmp);    pos=1;    for(int i=n;i>=1&&pos<=m;i--) {        while(re[pos].r==i&&pos<=m)ans[re[pos].id]+=f(tx.query(re[pos].d-1))+f(ty.query(n-re[pos].u)),pos++;        tx.add(a[i]),ty.add(n-a[i]+1);    }    for(int i=1;i<=m;i++)ans[re[i].id]+=f(n),ans[re[i].id]-=f(re[i].l-1)+f(n-re[i].r)+f(n-re[i].u)+f(re[i].d-1);    for(int i=1;i<=m;i++)cout<<ans[i]<<endl;    return 0;}
原创粉丝点击