一道codeforces题目引发的差分学习
题目:B. Suffix Operations
题意:给定一个长为n的数组a,你可以进行两种操作:1).后缀+1; 2)后缀-1; 问需要最少多少步操作你才能使得数组中元素全部相等,并且首先你可以改变其中任何一个元素成为任何一个数,并且不被计入步数
思路:
首先来看一下数组中大致分为这三种情况:举例
3 5 7 (上升式)这样中间的5变成3-7之间的任何一个数都能最终变成3
7 5 3 (下降式)与上述相同
7 3 5 (断崖式)最终要让他变成7,会产生浮动变化
通过上面的例子,就想到会用到差分数组(d[n]),总共的浮动次数是不变的,只需要统计如果一个数变化的时候影响最大的次数是多少,因为最终肯定会是出现阶段性的后面的数要变成它前面的数,所以要分情况讨论d[i]变化引起的d[i+1]的变化,具体看代码
代码:

1 #include<iostream>
2 #include<algorithm>
3 #include<cstdio>
4 #include<cmath>
5 #include<cstring>
6 #include<map>
7 #include<queue>
8 using namespace std;
9 const int maxx=2e5+1;//14.12
10 //找差分
11 long long int a[maxx]={0};
12 long long int d[maxx]={0};
13 int main(){
14 int n;
15 scanf("%d",&n);
16 while(n--){
17 int m;
18 scanf("%d",&m);
19
20 long long int sum=0;
21 for(int i=1;i<=m;i++){
22 scanf("%lld",&a[i]);
23 d[i]=a[i]-a[i-1];//差分数组
24 if(i>1){
25
26 sum+=abs(d[i]);
27 }
28 }
29
30 long long int maxn=0;
31 for(int i=1;i<=m;i++){
32 long long int x=abs(d[i]),y=abs(d[i+1]);
33 if(i==1){
34 maxn=max(maxn,abs(d[2]));
35 }else if(i==m){
36 maxn=max(maxn,abs(d[m]));
37 }else{
38 long long int y1;
39 if(d[i]>0){
40 y1=d[i+1]+x;
41 }else{
42 y1=d[i+1]-x;
43 }
44 maxn=max(maxn,x+y-abs(y1));
45 }
46 }
47 sum-=maxn;
48 printf("%lld\n",sum);
49
50
51 }
52 }
差分数组/前缀和的应用:
主要就是对数组中的数字进行操作,通过小区间波动改变一整个数组
1.HDU-1556 Color the Ball http://acm.hdu.edu.cn/showproblem.php?pid=1556
思路:一开始以为直接用a[maxx]数组进行遍历循环就行,结果TLE掉了,时间复杂度是O(n2),结果看了看并没有这么简单,应该是用两个数组,一个存储实际值(显然初始值都是0)c[n],一个存储浮动变化d[n]
d:0 1 0 0 -1
c:0 1 1 1 0
这样看来也有一些逆向前缀和的想法,存储的时候先存储d[i],然后按照前缀和的想法进行输出,这样时间复杂度就是O(n)
代码:

1 #include<iostream>
2 #include<algorithm>
3 #include<cstdio>
4 #include<cmath>
5 #include<cstring>
6 #include<map>
7 #include<queue>
8 using namespace std;
9 const int maxx=2e5+1;//14.12
10 int main(){
11 int n;
12 while(~scanf("%d",&n)){
13 int a[maxx]={0};
14 if(n==0){
15 break;
16 }
17 int c[maxx]={0};
18 for(int i=1;i<=n;i++){
19 int t,b;
20 scanf("%d %d",&t,&b);
21 c[t]++;
22 c[b+1]--;
23 }
24 int sum=0;
25 for(int i=1;i<=n;i++){
26 sum+=c[i];
27 printf("%d",sum);
28 if(i<n){
29 printf(" ");
30 }
31 }
32 printf("\n");
33 }
34 }
2.POJ -3263 Tallest Cow http://poj.org/problem?id=3263
思路:一开始想着用数组的加加减减,还是所有的从0开始,看他们的相对大小就好了,结果发现做的时候两边端点都加加,中间的都减减,这样出来的结果就是错的,后来发现差分数组想错了,并不是这样,而且这样也会TLE掉,这个题目中问的是最高多少,而且同时加减这样端点和中间就会差2而不是1,所以让所有的牛最初始的高度是h,然后再建立一个数组b[n]存储差分值,x,y为区间端点,b[x+1]--,b[y]++,而且这个题还需要区间判重一下,见代码
代码:

1 #include<iostream>
2 #include<cstdio>
3 #include<algorithm>
4 #include<cstring>
5 #include<string>
6 #include<cmath>
7 #define ll long long
8 #define mem(a,b) memset(a,b,sizeof(a))
9 using namespace std;
10 const int inf=0x3f3f3f3f;
11 const int mm=1e4+10;
12 int a[mm],b[mm];
13 int vis[mm][mm];
14 int main(){
15 int n,pos,h,r;
16 scanf("%d%d%d%d",&n,&pos,&h,&r);
17 for(int i=0;i<=h+1;i++)
18 a[i]=0;
19 int x,y;
20 for(int i=1;i<=r;i++){
21 scanf("%d%d",&x,&y);
22 if(x>y) swap(x,y);//
23 if(vis[x][y])//判重
24 continue;
25 vis[x][y]=1;
26 b[x+1]--;//后面的减少
27 b[y]++;//前面的增加
28 }
29 for(int i=1;i<=n;i++){
30 a[i]=a[i-1]+b[i];
31 printf("%d ",a[i]);
32 }
33 return 0;
34 }
TLE掉的代码:

1 #include<iostream>
2 #include<algorithm>
3 #include<cstdio>
4 #include<cmath>
5 #include<cstdio>
6 using namespace std;
7 const int maxx=1e5+10;
8 int main(){
9 int n,ii,h,r;
10 cin>>n>>ii>>h>>r;
11 int a[maxx]={0};
12 for(int i=1;i<=n;i++){
13 a[i]=h;
14 }
15 for(int i=0;i<r;i++){
16 int num1,num2;
17 scanf("%d %d",&num1,&num2);
18 if(num1>num2){
19 swap(num1,num2);
20 }
21 for(int j=num1+1;j<num2;j++){
22 a[j]--;
23 }
24 }
25 for(int i=1;i<=n;i++){
26 printf("%d ",a[i]);
27 }
28 }
一道codeforces题目引发的差分学习的更多相关文章
- 一道算法题目, 二行代码, Binary Tree
June 8, 2015 我最喜欢的一道算法题目, 二行代码. 编程序需要很强的逻辑思维, 多问几个为什么, 可不可以简化.想一想, 二行代码, 五分钟就可以搞定; 2015年网上大家热议的 Home ...
- 增强学习(五)----- 时间差分学习(Q learning, Sarsa learning)
接下来我们回顾一下动态规划算法(DP)和蒙特卡罗方法(MC)的特点,对于动态规划算法有如下特性: 需要环境模型,即状态转移概率\(P_{sa}\) 状态值函数的估计是自举的(bootstrapping ...
- 强化学习读书笔记 - 06~07 - 时序差分学习(Temporal-Difference Learning)
强化学习读书笔记 - 06~07 - 时序差分学习(Temporal-Difference Learning) 学习笔记: Reinforcement Learning: An Introductio ...
- 之前同事问到的一道python题目
Python面试题 之前同事问了一道Python题目如下,暂时归类为面试题 题目:把类似'123.456'的字符串转换成浮点型数据 方法一: >>> print '{:.3f}'.f ...
- Binary Search Tree 以及一道 LeetCode 题目
一道LeetCode题目 今天刷一道LeetCode的题目,要求是这样的: Given a binary search tree and the lowest and highest boundari ...
- 一道面试题引发的对 Java 内存模型的一点疑问
一道面试题引发的对Java内存模型的一点疑问 问题描述 如上图所示程序,按道理,子线程会通过 num++ 操作破坏 while 循环的条件,从而终止循环,执行最后的输出操作.但在我的多次运行中,偶尔会 ...
- js 一道题目引发的正则的学习
正则表达式中的特殊字符 字符 含意 \ 做为转意,即通常在"\"后面的字符不按原来意义解释,如/b/匹配字符"b",当b前面加了反斜杆后/\b/,转意为匹配一个 ...
- 一道原生js题目引发的思考(鼠标停留区块计时)
我瞎逛个啥论坛,发现了一个题目,于是本着练手的心态就开始写起来了,于是各种问题接踵而至,收获不小. 题目是这样的: Demo: mouseenter与mouseover区别demo 跨浏览器的区块计数 ...
- 一道面试题引发的思考(C#值类型和引用类型)
某年某月,笔者去面试招行的一个外包项目,辗转来到面试地点以后,面试官给了我一份试卷,试卷只有两道题目,其中一道是这样的: 阅读以下程序 class Program { struct Point { p ...
随机推荐
- python-6-1
1.定义一个时间戳转换成格式化时间的函数import time def timestamp_to_fomat(timestamp= None,format ='%Y-%m-%d %H:%M:%S' ) ...
- od快捷键
视图.查看相关: Alt+l 记录 Alt+e 可执行模块 Alt+m 内存 Alt+c cpu(反汇编视图) Ctrl+p 补丁 Alt+k 调用堆栈 Alt+b 断点 Alt+f5 设置窗口总在 ...
- 攻防世界 reverse 进阶 -gametime
19.gametime csaw-ctf-2016-quals 这是一个小游戏,挺有意思的 's'-->' ' 'x'-->'x' 'm'-->'m' 观察流程,发现检验函 ...
- 删除文件--rm
rm file 删除文件 rm -r dir 删除指定文件夹及文件夹下的所有内容 rm -rf dir 强制删除指定文件夹及文件夹下的所有内容
- Markdown排版介绍
如何排版章节 Markdown: 大标题 ========== 小标题 ---------- # 一级标题 ## 二级标题 ### 三级标题 #### 四级标题 例如 三级 和四级 发布后的效果: 三 ...
- 一键生成dotnet5项目解决方案
> 作为一名从2002年.Net 1.0一路走来的老码农,也持续跟进了dotnet core 1.0~3.1的变革,并不离不弃的玩起了dotnet 5. 每次接到新项目,都要从头搭建项目解决方案 ...
- 1003 Emergency (25分)
As an emergency rescue team leader of a city, you are given a special map of your country. The map s ...
- 488. Zuma Game
Think about Zuma Game. You have a row of balls on the table, colored red(R), yellow(Y), blue(B), gre ...
- 5-tcp套接字服务端编程
import socket 1.创建套接字 sockfd= socket.socket(socket_family = AF_INIT,socket_type=SOCK_STREAM,proto) 功 ...
- Sublime Text 3.1 3170 / 3176 注册码(附降级与禁止更新方法)
3.1 3176 可用注册码 127.0.0.1 www.sublimetext.com 127.0.0.1 license.sublimehq.com ----- BEGIN LICENSE --- ...