zoukankan      html  css  js  c++  java
  • P4231 三步必杀

    题目描述

    洛谷

    长度为 \(n\) 的序列,\(m\) 次操作,每次操作区间加等差数列,最后询问序列元素的异或和。

    数据范围: \(n\leq 10^7, m\leq 3\times 10^5\)

    solution

    我们手玩一下样例,对等差数列进行差分,会得到一个这样的数列

    2,2,2,2,2,-10

    发现我们还要每次都遍历一遍,给差分数组加上,这样复杂度会很高。

    我们考虑对差分数组在进行一遍差分,就会变成

    2 0 0 0 0 ,-12,12

    这样你就会发现,我们只要给四个位置加上就行了。

    分别是 dd[l] ,dd[l+1],dd[r+1],dd[r+2](dd为对差分数组进行差分之后的结果)

    设等差数列的公差为t,首项为st,尾项为en

    那么 dd[l] += st; dd[l+1] += t-st; dd[r+1] -= en+t; dd[e+2] += en+t;

    之后我们对dd数组求一下前缀和,就可以得到差分数组。

    在对差分数组求一下前缀和,就是改变后的序列.

    代码

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    int n,m,l,r,st,en,t;
    long long ans,maxn,d[10000010],sum[10000010],a[10000010];
    inline int read()
    {
    	int s = 0, w = 1; char ch = getchar();
    	while(ch < '0' || ch > '9'){if(ch == '-') w = -1; ch = getchar();}
    	while(ch >= '0' && ch <= '9'){s = s * 10+ch -'0'; ch = getchar();}
    	return s * w;
    }
    int main()
    {
    	n = read(); m = read();
    	for(int i = 1; i <= m; i++)
    	{
    		l = read(); r = read(); st = read(); en = read();
    		t = (en - st) / (r-l);//t是等差数列的公差
    		d[l] += st;//上面的柿子
    		d[l+1] += t-st;
    		d[r+1] -= en+t;
    		d[r+2] += en;//d是对差分数组差分得到的结果
    	}
    	for(int i = 1; i <= n; i++)
    	{
    		a[i] = a[i-1] + d[i];//a为差分数组
    		sum[i] = sum[i-1] + a[i];//sum为改变之后的序列
    		ans ^= sum[i];
    		maxn = max(maxn,sum[i]); 
    	}
    	printf("%lld %lld\n",ans,maxn);
    	return 0;
    }
    

    ENDING

  • 相关阅读:
    各大搜索引擎的User-Agent
    xxx couldn't be loaded because it has not been added to the build settings.
    C#解压、压缩RAR文件
    [转载]C# Random 生成不重复随机数
    [转载]如何打一手好Log
    MongoDB服务器启动异常 1067
    [转载]Asp.net MVC2 与 MVC3 路由调试好帮手RouteDebug 与 RouteDebugger
    [转载]C#中获取时间戳(UnixTime)的方法
    C# winform 弹出输入框
    设计与框架
  • 原文地址:https://www.cnblogs.com/genshy/p/13417581.html
Copyright © 2011-2022 走看看