Contest_5 0612 By lhq
来源:互联网 发布:东线德军 知乎 编辑:程序博客网 时间:2024/05/22 21:29
题目来源:学军中学NOIP2013提高组原创模拟题day1
https://wenku.baidu.com/view/c766b6b7915f804d2a16c141.html?from=search
Solution
1.装果子 关键词:二分
二分V,然后每次O(n)判断一遍。如果可以装进全部的果子就二分左区间,如果不行就二分右区间。
开long long是必然的。
时间复杂度:O(nlog(2,10^14))
2.零件加工 关键词:贪心
按照t/s升序排序然后计算,比较大小的时候注意交叉相乘。
详细证明见HK’blog:http://blog.csdn.net/yuyaohekai/article/details/73182025
对于最后20%的数据相乘时可以使用二进制乘法以避免高精度
时间复杂度:O(nlog2n)
3.种树 关键词:差分约束系统 or 贪心
解法一:
开一个s数组记录前缀和。
根据题意我们可以得到3个约束条件:
s[r]-s[l-1]≥c,①
s[i]≥s[i-1],②
s[i]-s[i-1]≤k,③
根据①得s[l]-s[r]≤-c,在r和l-1之间连一条权值为-c的边。
根据②得s[i-1]-s[i]≤0,在i和i-1之间连一条权值为0的边。
根据③在i-1和i之间连一条权值为k的边。
50分算法:Bellman-Ford。
时间复杂度:O(nm)
70分算法:SPFA。
时间复杂度:O(km)
100分算法:
观察到最大可能需要连150w条边,因此我们要考虑有些边是否需要连。
我们可以只根据条件①计算,每次更新后O(n)检查是否满足条件②和③,如果不满足就修改,这样只用连50w条边,可以过全部数据。
Tip:事实上SPFA可以过100%
解法二: 贪心
题目中要求要种树种得少,就要使一棵树给多个区间使用,这样,尽量在重叠区间种树即可,而重叠位置一定是区间尾部。处理问题时,先按所有区间的结束位置排序,若结束位置相同,则按开始位置从大到小排序。之后依次处理每个区间,先在第一个区间尾部种满足要求的树,对下一个区间,看差多少棵就在该区间尾部种多少。
【算法步骤】:
1.先快排
2.对每个区间依次处理
a.从前到后扫描这个区间,统计点的个数;
b.若点的个数超过了要求的点数,则continue;
c.从该区间后向前扫描,添加覆盖点。
3.输出ans
Tip:这种方法只适用于小数据,对于大数据我们可以用树状数组加快求和,即过程a,还可以用并查集的方法来加速种树过程c,当有一段区间的树种满时把它与前一个区间合并就行了。
总结:
T1水过,T2没想到贪心,T3排序打错。。
T2的证明中我们有了发现:那就是比较之后的两种选择哪种更优,而不是拿出一种来算,有点差分约束的思想
CODE
T1
#include<bits/stdc++.h>using namespace std;#define ll long longll a[100100],n,m;ll read(){ ll w=0,ch=getchar(); while (ch<'0'||ch>'9') ch=getchar(); while (ch>='0'&&ch<='9') w=w*10+ch-48,ch=getchar(); return w; }bool check(ll v){ ll num=1,bag=v; for (ll i=1;i<=n;i++) if (bag>=a[i]) bag-=a[i]; else if (num<m) num++,bag=v-a[i]; else return false; return true; }ll binary_answer(ll l,ll r){ ll ans; while (l<=r) { ll mid=(l+r)>>1; if (check(mid)) ans=mid,r=mid-1; else l=mid+1; } return ans; }int main(){ n=read(); m=read(); for (ll i=1;i<=n;i++) a[i]=read(); ll min_val=0,max_val=0; for (ll i=1;i<=n;i++) min_val=max(min_val,a[i]),max_val+=a[i]; ll ans=binary_answer(min_val,max_val); printf("%lld",ans); return 0;}
T2
#include<bits/stdc++.h>using namespace std;#define ll long long#define MAXN 100010ll n,m,tot,ans;struct node { ll t,s;}a[MAXN];bool cmp(node a,node b){ return a.t*b.s<a.s*b.t;}ll read(){ ll w=0,ch=getchar(); while (ch<'0'||ch>'9') ch=getchar(); while (ch>='0'&&ch<='9') w=w*10+ch-48,ch=getchar(); return w; }ll mul(ll a,ll b){ ll ans=0; while (b) { if (b&1) ans=(ans+a)%m; a=(a+a)%m; b=b>>1; } return ans; }int main(){ n=read(); m=read(); for (int i=1;i<=n;i++) a[i].t=read(),a[i].s=read(); sort(a+1,a+n+1,cmp); for (int i=1;i<=n;i++) { ans=(ans+mul(tot,a[i].s))%m; tot=(tot+a[i].t)%m; } cout<<ans<<endl; return 0;}
T3 差分约束
#include<bits/stdc++.h>using namespace std;const int MAXN=500010,MAXM=1500010;int Head[MAXN],Next[MAXM],dis[MAXN],n,m,tot;int que[MAXN*2];bool vis[MAXN];struct Edge{ int v,w; Edge():v(0),w(0){}; Edge(int _v,int _w):v(_v),w(_w){};}E[MAXM];int read(){ int w=0,ch=getchar(); while (ch<'0'||ch>'9') ch=getchar(); while (ch>='0'&&ch<='9') w=w*10+ch-48,ch=getchar(); return w; }void AddEdge(int u,int v,int w){ tot++; Next[tot]=Head[u]; Head[u]=tot; E[tot]=Edge(v,w);}void spfa(int s){ int l,r; memset(dis,0x3f,sizeof(dis)); memset(vis,false,sizeof(vis)); dis[s]=0; l=1; r=2; que[l]=s; vis[s]=true; while (l<r) { int u=que[l]; l++; vis[u]=false; for (int i=Head[u];i;i=Next[i]) { int v=E[i].v,w=E[i].w; if (dis[v]>dis[u]+w) { dis[v]=dis[u]+w; if (!vis[v]) que[r++]=v,vis[v]=true; } } }}int main(){ n=read(); m=read(); for (int i=1;i<=n;i++) { int k=read(); AddEdge(i,i-1,0),AddEdge(i-1,i,k); } for (int i=1;i<=m;i++) { int x,y,z; x=read(); y=read(); z=read(); AddEdge(y,x-1,-z); } spfa(n); cout<<-dis[0]<<endl; return 0;}
T3 贪心
#include<bits/stdc++.h>using namespace std;#define ll long longconst ll MAXN=5e5+100,MAXM=5e5+100;struct node{ ll l,r,c;}a[MAXM];ll n,m,k[MAXN],tree[MAXN],BIT[MAXN],fa[MAXN];ll read(){ ll w=0,ch=getchar(); while (ch<'0'||ch>'9') ch=getchar(); while (ch>='0'&&ch<='9') w=w*10+ch-48,ch=getchar(); return w; }bool cmp(const node &a,const node &b){ if (a.l==b.l && a.r==b.r) return a.c>b.c; if (a.r==b.r) return a.l>b.l; return a.r<b.r;}//BIT;void add(ll x,ll val){ for (ll i=x;i<=n;i+=i&-i) BIT[i]+=val;}ll sum(ll x){ ll ans=0; for (ll i=x;i>0;i-=i&-i) ans+=BIT[i]; return ans;}ll sum(ll x,ll y){ return sum(y)-sum(x-1); }//set;void make_set(){ for (ll i=1;i<=n;i++) fa[i]=i;}ll getfa(ll x){ if (fa[x]==x) return x; fa[x]=getfa(fa[x]); return fa[x];}void merge(ll x,ll y){ x=getfa(x); y=getfa(y); if (x!=y) if (y>x) fa[y]=x; else fa[x]=y;}//solve;void solve(){ make_set(); for (ll i=1;i<=m;i++) { ll num=a[i].c; num-=sum(a[i].l,a[i].r); if (num<=0) continue; for (ll j=a[i].r;j>=a[i].l && num>0;j=getfa(j)) { if (k[j]>tree[j]) if (num<=k[j]-tree[j]) add(j,num),tree[j]+=num,num=0; else num-=k[j]-tree[j],add(j,k[j]-tree[j]),tree[j]=k[j]; if (tree[j]==k[j]) merge(j-1,j); } }}int main(){ n=read(); m=read(); for (ll i=1;i<=n;i++) k[i]=read(); for (ll i=1;i<=m;i++) a[i].l=read(),a[i].r=read(),a[i].c=read(); sort(a+1,a+1+m,cmp); solve(); ll ans=0; for (ll i=1;i<=n;i++) ans+=tree[i]; printf("%lld",ans); return 0;}
- Contest_5 0612 By lhq
- Contest_5 0616 By lhq
- Contest_5 0614 By lhq
- Contest_6 0619 By lhq
- by
- group by order by
- group by + order by
- hive order by,sort by,distributed by
- group by
- Published by
- connect by
- by now
- connect by ~~~~
- group by
- by x_tr
- order by
- group by
- group by
- 敏捷测试理论以及实践
- 一次测试引发的探索:关于分号在java web中的一个特性
- kafka设置外网消费者
- PHP中使用CER公钥的方法
- 利用广播进行两个Activity之间的交互
- Contest_5 0612 By lhq
- 几维安全分享安卓apk反编译的流程及注意事项
- 线性SVM
- 敏捷测试理论以及实践
- 简易轮播图
- java代码自动生成UML-工具集
- TypeScript入门01
- 40-Combination Sum II
- 转:深入研究mysql中group by与order by取分类最新时间内容