7.18 DP考试解题报告

今天的考试真的是天崩地裂,写了的三个题全炸。。。然而谁叫我弱+不注意细节呢???真的要扇耳光。。。

T1:
题意:一段区间的高度为这个区间中高度的最小值,给定n个宽度,求每个宽度的期望高度

40% :算出长度为x的区间的所有的最小值的取值的和,除以总的方案数(n-x+1),用ST表预处理可以n^2;(记得开long long)

100%:对于每个点求出他取最小值的区间,即用两遍单调栈求出左,右边第一个小于他的值。。。记为l[i],和r[i],这一步和影魔很像;

对于当前这一个点,考虑以他为最小值,能贡献给多少个区间。。。

记l1=i-l[i]+1,l2=r[i]-i+1;

对于长度L在[1,min(l1,l2)]的区间,可以贡献L*a[i];

对于长度L在[min(l1,l2)+1,max(l1,l2)],可以贡献min(l1,l2)*a[i];

对于长度L在[max(l1,l2)+1,r[i]-l[i]+1],可以贡献(r[i]-l[i]+1-L+1)*a[i];

(算对长度为L的区间的贡献就是看长度为L的区间在[l[i],r[i]]内移动能包含i点多少次);

然后涉及多次修改和一次询问,考虑序列差分。。。然而这是一个优秀的差分。。。

发现修改有两种,一个是一段区间加上相同的值,另一个是和每个点本身的长度有关。。。

所以建两个差分数组,一个记录正常的差分,一个记录L前的系数,这样第三个情况需要拆成两个修改来维护。。。

其实说了这么多,代码还是很短的。。。

// MADE BY QT666
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstring>
#define int long long
using namespace std;
typedef long long ll;
const int N=2000000;
int gi(){
  int x=0;
  char ch=getchar();
  while(ch<‘0‘||ch>‘9‘) ch=getchar();
  while(ch>=‘0‘&&ch<=‘9‘) x=x*10+ch-‘0‘,ch=getchar();
  return x;
}
int n,m,a[N],q[N],tail,l[N],r[N],ans[N],cf1[N],cf2[N];
main(){
  freopen("fence.in","r",stdin);
  freopen("fence.out","w",stdout);
  scanf("%lld",&n);for(int i=1;i<=n;i++) a[i]=gi();
  tail=0;q[++tail]=0;
  for(int i=1;i<=n;i++){
    while(tail>0&&a[i]<=a[q[tail]]) tail--;
    l[i]=q[tail]+1;q[++tail]=i;
  }
  tail=0;q[++tail]=n+1;
  for(int i=n;i>=1;i--){
    while(tail>0&&a[i]<a[q[tail]]) tail--;
    r[i]=q[tail]-1;q[++tail]=i;
  }
  for(int i=1;i<=n;i++){
    int l1=i-l[i]+1,l2=r[i]-i+1;
    cf1[1]+=a[i];cf1[min(l1,l2)+1]-=a[i];
    cf2[min(l1,l2)+1]+=a[i]*min(l1,l2);cf2[max(l1,l2)+1]-=a[i]*min(l1,l2);
    cf2[max(l1,l2)+1]+=a[i]*(r[i]-l[i]+2),cf2[r[i]-l[i]+2]-=a[i]*(r[i]-l[i]+2);
    cf1[max(l1,l2)+1]-=a[i],cf1[r[i]-l[i]+2]+=a[i];
  }
  for(int i=1;i<=n;i++) cf1[i]+=cf1[i-1],cf2[i]+=cf2[i-1],ans[i]=cf1[i]*i+cf2[i];
  scanf("%lld",&m);while(m--){int x=gi();printf("%.5f\n",ans[x]*1.0/(n-x+1));}
  return 0;
}

T2:

题意:由于题面描述过于生动,令人影响深刻,所以不再描述。。。

做法:考虑到要尽量在v大的那天开,且一天就要开完,且前面可以养精蓄锐留到v大的那天来开。。。

所以考虑维护一个v递减的单调栈来对决策进行调整,在弹栈的过程中分情况讨论一下调整即可。。。

if(life[i]+life[q[tail]]<=E) life[i]+=life[q[tail],Ans-=v[q[tail]]*life[q[tail]];//把第q[tail]天的精力留到第i天

if(life[i]+life[q[tail]]>E) Ans-=(E-life[i])*v[q[tail]],life[i]=E;//和上面同理,yy一下

然后有一个史前巨坑:R>E,如果没有R=min(R,E)就会光荣baoling。。。。

// MADE BY QT666
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#define int long long
using namespace std;
typedef long long ll;
const int M=1000050;
int T,E,R,N,v[M],life[M],q[M],tail,Ans;
main(){
  freopen("power.in","r",stdin);
  freopen("power.out","w",stdout);
  scanf("%lld",&T);
  while(T--){
    scanf("%lld%lld%lld",&E,&R,&N);R=min(R,E);
    for(int i=1;i<=N;i++) scanf("%lld",&v[i]);
    memset(life,0,sizeof(life));tail=0;Ans=0;
    q[++tail]=1;life[1]=E;Ans=life[1]*v[1];
    for(int i=2;i<=N;i++){
      life[i]=R;
      while(tail>0&&v[q[tail]]<v[i]){
	if(life[i]+life[q[tail]]>E) Ans-=(E-life[i])*v[q[tail]],life[i]=E;
	else Ans-=life[q[tail]]*v[q[tail]],life[i]+=life[q[tail]];
	tail--;
      }
      Ans+=life[i]*v[i];q[++tail]=i;
    }
    printf("%lld\n",Ans);
  }
  return 0;
}

T4:

题意:关路灯,见codevs。。。

我真的是太弱了,这种DP都打不出来。。。

dp[i][j][0]表示关完了区间[i,j]的灯,然后在区间的左端点的最少花费。。。

dp[i][j][1]表示关完了区间[i,j]的灯,然后在区间的右端点的最少花费。。。

然后用功率的前缀和表示其他区间的能耗情况。。。

然后转移就是4种:

从左到左,从右到左,从右到右,从左到右。。。每次至移动一位来转移。。。

// MADE BY QT666
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#define RG register
#define Min(a,b) (a<b?a:b)
const int N = 1050;
using namespace std;
typedef long long ll;
inline int gi(){
  RG char ch=getchar();RG int x=0;
  while(ch<‘0‘ || ch>‘9‘) ch=getchar();
  while(ch>=‘0‘ && ch<=‘9‘) x=x*10+ch-‘0‘,ch=getchar();
  return x;
}
ll d[N],w[N],dp[N][N][2];
int main(){
  freopen("light.in","r",stdin);
  freopen("light.out","w",stdout);
  int n=gi(),m=gi(); RG int i,j; ll z;
  for (i=1; i<=n; ++i) d[i]=gi(),w[i]=w[i-1]+gi();
  memset(dp,56,sizeof(dp));
  dp[m][m][0]=dp[m][m][1]=0;
  for (i=m; i; --i)
    for (j=m; j<=n; ++j){
      z=w[n]-w[j]+w[i-1];
      dp[i-1][j][0]=Min(dp[i-1][j][0],dp[i][j][0]+(d[i]-d[i-1])*z);
      dp[i-1][j][0]=Min(dp[i-1][j][0],dp[i][j][1]+(d[j]-d[i-1])*z);
      dp[i][j+1][1]=Min(dp[i][j+1][1],dp[i][j][0]+(d[j+1]-d[i])*z);
      dp[i][j+1][1]=Min(dp[i][j+1][1],dp[i][j][1]+(d[j+1]-d[j])*z);
    }
  printf("%lld",Min(dp[1][n][0],dp[1][n][1]));
  return 0;
}  
时间: 2024-08-04 21:17:41

7.18 DP考试解题报告的相关文章

2019.10.18考试解题报告

总结 期望得分:\(100 + 100 + 10\) 实际得分:\(0 + 20 + 10\) 完美. 今天的考试格外完美,\(T1\)做了*\(2.5h\),最后换来了\(0\)分的好成绩,史无前例,美妙绝伦,我竟然不删调试,做得?好. \(T2\)是个好题,是个好阅读题,\(n\)和\(m\)写反了,样例给的是\(n\)和\(m\)相等的情况,最终完美\(100->20\),我竟然这么粗心,题目竟然没读好,做得?好. \(T3\)没时间了,都耗在\(T1\)上了,可惜\(T1\)还没有分,做

2014年秋季大学先修课考试 解题报告

A:细菌的战争 总时间限制:  1000ms 内存限制:  65536kB 描述 有两种细菌,一种是有害菌,繁殖能力很强,每小时会繁殖一倍:另一种是有益菌,繁殖能力较弱,每小时能繁殖百分之五.但在单位体积内,当有害菌数量超过一 百万时,多出的细菌会因为密度太大而迅速死亡,直到细菌数量下降到一百万.已知每个有益菌每小时能消灭一个有害菌.给定单位体积内有害菌和有益菌的初始数 量,请问多少小时后,有害菌将被有益菌消灭干净? 输入 输入的第一行为一个整数n,表示后边有n组数据.每组数据占一行,有两个整数

2014年春季大学先修课考试 解题报告

A:吃糖果 总时间限制:  1000ms 内存限制:  65536kB 描述 名名的妈妈从外地出差回来,带了一盒好吃又精美的巧克力给名名(盒内共有 N 块巧克力,20 > N >0).妈妈告诉名名每天可以吃一块或者两块巧克力.假设名名每天都吃巧克力,问名名共有多少种不同的吃完巧克力的方案.例如:如果N=1,则名名第1天就吃掉它,共有1种方案:如果N=2,则名名可以第1天吃1块,第2天吃1块,也可以第1天吃2块,共有2种方案:如果N=3,则名名第1天可以吃1块,剩2块,也可以第1天吃2块剩1块,

Codeforces Round #396 (Div. 2) C题Mahmoud and a Message(dp)解题报告

Mahmoud wrote a message s of length n. He wants to send it as a birthday present to his friend Moaz who likes strings. He wrote it on a magical paper but he was surprised because some characters disappeared while writing the string. That's because th

暑假第二次考试 冲刺Noip2017模拟赛2 解题报告——五十岚芒果酱

题1 牛跑步(running) [题目描述] 新牛到部队,CG 要求它们每天早上搞晨跑,从 A 农场跑到 B 农场.从 A 农场到 B 农场中有 n-2 个路口,分别标上号,A 农场为 1 号,B 农场为 n 号,路口分别为 2...n-1 号,从 A 农场到 B 农场有很多条路径可以到达,而 CG 发现有的路口是必须经过的,即每条路径都经过的路口,CG 要把它们记录下来,这样 CG 就可以先到那个路口,观察新牛们有没有偷懒,而你的任务就是找出所有必经路口. [输入格式] 第一行两个用空格隔开的

10.30 NFLS-NOIP模拟赛 解题报告

总结:今天去了NOIP模拟赛,其实是几道USACO的经典的题目,第一题和最后一题都有思路,第二题是我一开始写了个spfa,写了一半中途发现应该是矩阵乘法,然后没做完,然后就没有然后了!第二题的暴力都没码QAQ 现在我来写解题报告了,有点饿了QAQ.. 第一题 题目 1: 架设电话线 [Jeffrey Wang, 2007] 最近,Farmer John的奶牛们越来越不满于牛棚里一塌糊涂的电话服务,于 是,她们要求FJ把那些老旧的电话线换成性能更好的新电话线.新的电话线架设 在已有的N(2 <=

2016.8.29 LGTB解题报告

考试总结: 1.这道题还是花了不少的时间的,特别是对拍啊之类的,总是放不下,然后有一些实现的问题导致改错也改了很久: 解决方案:下一次在决定写程序的时候,一定要先在草稿纸上把实现算法的流程基本上写一次,精确到循环语句,判断语句的框架,把所有的情况都完整地考虑一次,确定没有问题了再写: 这道题犯了和上一套第二题同样的问题:证明的时间过长: 解决方案:在解题时把流程规范化,在证明了算法正确性以后就放下了,不要总是把它提出来! 2.这道题的数据范围特别小,所以可以很容易地想到状压DP,然后考虑到互质的

USACO Section2.1 Subset Sums 解题报告 【icedream61】

subset解题报告------------------------------------------------------------------------------------------------------------------------------------------------[题目] 把1~N分成两组,让他们的和相等,请问这样的分组有多少种? 但顺序可以颠倒,比如{3}.{2,1}和{2,1}.{3}算作一种.[数据范围] 1<=N<=39[输入样例] 7[输出

2020-3-14 acm训练联盟周赛Preliminaries for Benelux Algorithm Programming Contest 2019 解题报告+补题报告

2020-3-15比赛解题报告+2020-3-8—2020-3-15的补题报告 2020-3-15比赛题解 训练联盟周赛Preliminaries for Benelux Algorithm Programming Contest 2019  A建筑(模拟) 耗时:3ms 244KB 建筑 你哥哥在最近的建筑问题突破大会上获得了一个奖项 并获得了千载难逢的重新设计城市中心的机会 他最喜欢的城市奈梅根.由于城市布局中最引人注目的部分是天际线, 你的兄弟已经开始为他想要北方和东方的天际线画一些想法