i=i++的迷惑

   学习过一门计算机语言的人一定知道j=i++的运算结果,整个表达式的值为i,而i的值变为i+1;那么i=i++又是一个什么情况呢?下面分别用java 和 c 两种语言来做个测试:

JAVA:

public class test{

 public static void main(String args[]){

  inti,j;

  i=0;

  for(j=0;j<5;j++){

    i=i++;

   System.out.println("i="+i);

  }
 }
}

 

C程序:

#include<stdio.h>

main(){

  inti,j;

  i=0;

  for(j=0;j<5;j++){

    i=i++;

   printf("i=%d\n",i);

  }

}

你也许会问,这么简单的程序会有什么问题呢?是的,如果不相信的话,你可以运行一下这两个程序,得到的结果非常让人震惊。

第一个JAVA程序得出的结果如下:

i=0

i=0

i=0

i=0

i=0

而第二个C程序得出的结果如下:

i=1

i=2

i=3

i=4

i=5

   同样都是i=i++,为什么得出的结果会有这么大的差异呢?原来是在编译器上出了问题,java的编译器在遇到i++和i- -的时候会重新为变量运算分配一块内存空间,以存放原始的值,而在完成了赋值运算之后,将这块内存释放掉,下面首先看一下如果是j=i++的情况:

 

    i的原始值存放在后开辟的内存中,最后这个值将赋值给j,这样j=i++后,j就会得到i的值,而i又将自加,所以,在释放内存之后,原来存放j和i的地方将得到值将是:j(此时的值等于初始i值)和i(i自加后的值)。

明白了上面的问题,让我们接下来看看i=i++的情况:

所以这样最后一次循环内的结果仍旧是i(即0)。

而C语言中的i=i++就只是完成i++的内容,所以结论会不同。这种情况说明java和c的处理语法的机制不同,如果在程序中只输入i++就不会出现这个方面的问题,所以大家在以后的程序中如果使用到i=i++的时候要格外小心,一般只需要用i++就不会有问题了。


对于这道题目和这个代码,请你为我解释一下为什么要使用滑动窗口以及倍增状态的的定义,并为代码加上详细的注释: 代码: #include #include #include #include #define R register #define MAXN 1000010 typedef long long ll; using namespace std; ll n,k,m; ll p[MAXN]; ll f[MAXN],ff[MAXN],ans[MAXN]; int main() { scanf(“%lld%lld%lld”,&n,&k,&m); for(R ll i=1;i<=n;i++) { scanf(“%lld”,&p[i]); } f[1]=k+1; ll l=1,r=k+1; for(R ll i=2;i<=n;i++)//滑窗维护左右端点 { while(r+1<=n&&p[i]-p[l]>p[r+1]-p[i]) l++,r++; if(p[i]-p[l]>=p[r]-p[i]) f[i]=l; else f[i]=r; } for(R ll i=1;i<=n;i++) ans[i]=i;//初始跳0次 while(m)//倍增 { if(m&1) for(R ll i=1;i<=n;i++) ans[i]=f[ans[i]];//更新答案 m>>=1; memcpy(ff,f,sizeof(ff)); for(R ll i=1;i<=n;i++) f[i]=ff[ff[i]];//更新下一个跳到的点 } for(R ll i=1;i<=n;i++) printf("%lld ",ans[i]); return 0; } 题面: # P3509 [POI 2010] ZAB-Frog ## 题目描述 在一个特别长且笔直的 Byteotian 小溪的河床上,有 $n$ 块石头露出水面。它们距离小溪源头的距离分别为 $p_1 < p_2 < \cdots < p_n$。一只小青蛙正坐在其中一块石头上,准备开始它的跳跃训练。每次青蛙跳跃到距离它所在石头第 $k$ 近的石头上。具体来说,如果青蛙坐在位置 $p_i$ 的石头上,那么它将跳到这样的 $p_j$ 上,使得: $$ |\{ p_a : |p _ a - p _ i| < |p_j - p_i| \}| \le k \text{ and } |\{ p_a : |p _ a - p _ i| \le |p_j - p_i| \}| > k $$ 如果 $p_j$ 不是唯一的,那么青蛙在其中选择距离源头最近的石头。对于每一块石头分别计算,若青蛙从这块石头开始跳跃,经过 $m$ 次跳跃后最终会停留在哪一块石头上? ## 输入格式 标准输入的第一行包含三个整数 $n$、$k$ 和 $m$($1 \le k < n \le 1\,000\,000, 1 \le m \le 10^{18}$),用空格分隔,分别表示石头的数量、参数 $k$ 和计划跳跃的次数。第二行包含 $n$ 个整数 $p_j$($1 \le p_1 < p_2 < \cdots < p_n \le 10^{18}$),用空格分隔,表示小溪河床上连续石头的位置。 ## 输出格式 你的程序应在标准输出上打印一行,包含 $n$ 个整数 $r_1, r_2, \cdots, r_n$,用空格分隔。数字 $r_i$ 表示从输入顺序中的第 $i$ 块石头开始跳跃 $m$ 次后,青蛙最终停留的石头编号。 ## 输入输出样例 #1 ### 输入 #1 ``` 5 2 4 1 2 4 7 10 ``` ### 输出 #1 ``` 1 1 3 1 1 ``` ## 说明/提示 ### 样例 #1 解释: ![](https://cdn.luogu.com.cn/upload/image_hosting/yyilx2mp.png) 图中展示了青蛙从每块石头跳跃(单次跳跃)到的位置。 题面翻译由 ChatGPT-4o 提供。 提示: 1.预处理出每个点跳到离自己第k的点的编号,可以用一个类似滑动窗口的单调队列实现,具体见代码。不会的可以看看这道题 P1886 滑动窗口。 2.用倍增处理出每个点跳m次达到的点,即为答案。
最新发布
10-02
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值