暑假开始了,竞赛生活也开始了。
今天进行了校内赛。
先来一个样例解释
好萌啊!
第一题
【解题报告】
直接模拟相应数据结构,判断弹出元素是否和给定数字一致。注意可能会出现不合法的输入,需要特判弹出操作比插入操作多的情况。
代码
#include<cstdio>
#include<cstring>
#include<stack>
#include<queue>
#include<algorithm>
using namespace std;
const int N=1000;
int n,flag[5],opt,v,a,b,c,temp1,temp2;
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",&opt,&v);
if (opt==1)
{
temp1++;
s.push(v);
q.push(v);
heap.push(v);
}
if (opt==2)
{
temp2++;
if (s.empty()) flag[1]=1;
if (q.empty()) flag[2]=1;
if (heap.empty()) flag[3]=1;
if (!flag[1]) {a=s.top();s.pop();if(a!=v)flag[1]=1;}
if (!flag[2]) {b=q.front();q.pop();if(b!=v)flag[2]=1;}
if (!flag[3]) {c=heap.top();heap.pop();if(c!=v)flag[3]=1;}
}
}
if (temp1>=temp2)
{
for (int i=1;i<=3;i++)
if (!flag[i]) printf("YES\n");
else printf("No\n");
}
else printf("No\nNo\nNo\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<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
const int N=1e5+5;
int n;
long long ans,maxn=0,now=0;
int max(long long x,long long y)
{
if (x>=y) return x;
else return y;
}
struct event
{
long long num,tim,final,pre;
}plan[N];
bool cmp(event a,event b)
{
return a.final<b.final;
}
int main()
{
freopen("ming.in","r",stdin);
freopen("ming.out","w",stdout);
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
long long a,b;
plan[i].num=i;
scanf("%I64d%I64d",&a,&b);
plan[i].tim=a,plan[i].final=b;
plan[i].pre=b-a;
}
sort(plan+1,plan+n+1,cmp);
for (int i=1;i<=n;i++)
{
now+=plan[i].tim;
ans=max(0,now-plan[i].final);
if (ans>=maxn) maxn=ans;
}
printf("%I64d\n",maxn);
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<iostream>
#include<cmath>
#include<vector>
#include<map>
using namespace std;
const int N=1010;
const int mod=1000000007;
long long m,f[N],siz[N],a[N],b[N],c[N],d[N],l[N];
map<pair<long long,long long>,long long>mp;
long long dis(long long x,long long s,long long t)
{
if(x==0) return 0;
long long 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];
}
long long dfs(long long x,long long 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(long long 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;
long long 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]]);
long long 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(long long i=1;i<=m;++i)
printf("%I64d\n",f[i]);
return 0;
}