2017.7.3 机房测试(模拟,贪心,图论)

来源:互联网 发布:知乎老人助听器 编辑:程序博客网 时间:2024/04/29 09:15

这里写图片描述
【解题报告】
直接模拟相应数据结构,判断弹出元素是否和给定数字一致。注意可能会出现不合法的输入,需要特判弹出操作比插入操作多的情况。

代码如下:

#include<cstdio>#include<cstring>#include<algorithm>#include<stack>#include<queue>using namespace std;#define N 10010int n,a[N],b[N];bool flag[5];stack<int> S;queue<int> q;priority_queue<int> heap;int main() {    freopen("qu.in","r",stdin);    freopen("qu.out","w",stdout);    scanf("%d",&n);    for(int i=1;i<=n;++i)     {        scanf("%d%d",&a[i],&b[i]);        if(a[i]==1)         {            S.push(b[i]);            q.push(b[i]);            heap.push(b[i]);        }        if(a[i]==2)         {            if(S.empty()) flag[1]=1;            if(q.empty()) flag[2]=1;            if(heap.empty()) flag[3]=1;            if(!flag[1]) {int t1=S.top();S.pop();if(t1!=b[i]) flag[1]=1;}            if(!flag[2]) {int t2=q.front();q.pop();if (t2!=b[i]) flag[2]=1;}            if(!flag[3]) {int t3=heap.top();heap.pop();if (t3!=b[i]) flag[3]=1;}        }    }    for(int i=1;i<=3;++i)    {        if(!flag[i]) printf("YES\n");        else printf("No\n");        }    return 0;}

这里写图片描述
【解题报告】
考虑序列中只有两个元素的情况,此时两种可能多的排列对应答案分别为max(t1−d1,t1+t2−d2)max(t1−d1,t1+t2−d2),和max(t2−d2,t2+t1−d1)max(t2−d2,t2+t1−d1),我们希望选取其中的最小值。注意到t1−d1

include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define N 100010int n;int ans=0;struct NODE {    int t,d,sum;    NODE(){sum=0;}    friend bool operator<(const NODE &a,const NODE &b)     {return a.d<b.d||(a.d==b.d&&a.t<b.t);}}a[N];int main() {    freopen("ming.in","r",stdin);    freopen("ming.out","w",stdout);    scanf("%d",&n);    for(int i=1;i<=n;++i) scanf("%d%d",&a[i].t,&a[i].d);    sort(a+1,a+n+1);    a[0].sum=0;    for(int i=1;i<=n;++i)    {        a[i].sum=a[i-1].sum+a[i].t;        ans=max(ans,max(0,a[i].sum-a[i].d));        }    printf("%d\n",ans);    return 0;}

这里写图片描述
【解题报告】
每一棵树都由先前的两棵树构造而来,于是可以进行递推。
所求F(Ti)F(Ti)就是TiTi中每一对点的距离和,有

F(Ti)=F(Tai)+F(Tbi)+|Tbi|∑u∈Taid(u,ci)+|Tai|∑u∈Tbid(u,di)+|Tai||Tbi|li.F(Ti)=F(Tai)+F(Tbi)+|Tbi|∑u∈Taid(u,ci)+|Tai|∑u∈Tbid(u,di)+|Tai||Tbi|li.

设A(Ti,u)A(Ti,u)表示TiTi中所有点到uu的距离和,D(Ti,u,v)D(Ti,u,v)表示TiTi中uu到vv的距离,则

F(Ti)=F(Tai)+F(Tbi)+|Tbi|A(Tai,ci)+|Tai|A(Tbi,di)+|Tai||Tbi|li.F(Ti)=F(Tai)+F(Tbi)+|Tbi|A(Tai,ci)+|Tai|A(Tbi,di)+|Tai||Tbi|li.

不失一般,设u∈Taiu∈Tai,

A(Ti,u)=A(Tai,u)+A(Tbi,di)+|Tbi|(li+D(Tai,ci,u)).A(Ti,u)=A(Tai,u)+A(Tbi,di)+|Tbi|(li+D(Tai,ci,u)).

设u,v∈Taiu,v∈Tai,

D(Ti,u,v)=D(Tai,u,v).D(Ti,u,v)=D(Tai,u,v).

设u∈Tai,v∈Tbiu∈Tai,v∈Tbi,则

D(Ti,u,v)=D(Tai,u,ci)+li+D(Tbi,di,v.)D(Ti,u,v)=D(Tai,u,ci)+li+D(Tbi,di,v.)

可以发现递推式参数中的uu、vv都必然是某一个cici或didi,共2m2m个,所以A(Ti,u)A(Ti,u)的参数最多有2m22m2个取值,D(Ti,u,v)D(Ti,u,v)的参数最多有4m34m3个取值。记忆化递推解决。

代码如下:

#include<cstdio>#include<cstring>#include<algorithm>#include<map>using namespace std;#define N 1010#define mod 1000000007#define dnt long longdnt m,f[N],siz[N],a[N],b[N],c[N],d[N],l[N];map<pair<dnt,dnt>,dnt>mp;dnt dis(dnt x,dnt s,dnt t){    if(x==0) return 0;    dnt k=siz[a[x]];    if(s>=k&&t>=k) return dis(b[x],s-k,t-k);    else if(s<k&&t<k) return dis(a[x],s,t);    else if(s>=k) return dis(b[x],s-k,d[x])+dis(a[x],t,c[x])+l[x];    else return dis(b[x],t-k,d[x])+dis(a[x],s,c[x])+l[x];}dnt dfs(dnt x,dnt pos)//x 树编号,pos点编号 {    if(x==0) return 0;    if(mp[make_pair(x,pos)]) return mp[make_pair(x,pos)];    if(pos>=siz[a[x]])         return mp[make_pair(x,pos)]=dfs(b[x],pos-siz[a[x]])+dfs(a[x],c[x])+siz[a[x]]*(l[x]+dis(b[x],pos-siz[a[x]],d[x]));    else return mp[make_pair(x,pos)]=dfs(a[x],pos)+dfs(b[x],d[x])+siz[b[x]]*(l[x]+dis(a[x],pos,c[x]));}int main(){    freopen("zi.in","r",stdin);    freopen("zi.out","w",stdout);    scanf("%I64d",&m);    siz[0]=1;f[0]=0;    for(dnt i=1;i<=m;++i)    {        scanf("%I64d%I64d%I64d%I64d%I64d",&a[i],&b[i],&c[i],&d[i],&l[i]);        f[i]=(f[a[i]]+f[b[i]])%mod;        dnt part1=(siz[a[i]]%mod*siz[b[i]]%mod)%mod;        part1=(part1%mod*l[i]%mod)%mod;        f[i]=(f[i]%mod+part1%mod)%mod;        siz[i]=(siz[a[i]]+siz[b[i]]);        dnt a1=dfs(a[i],c[i])%mod,a2=dfs(b[i],d[i])%mod;         a1=(a1*siz[b[i]]%mod)%mod;        a2=(a2*siz[a[i]]%mod)%mod;        f[i]=(f[i]%mod+a1%mod+a2%mod)%mod;    }    for(dnt i=1;i<=m;++i)    printf("%I64d\n",f[i]);    return 0;}
阅读全文
0 0