Acwing 3729. 改变数组元素(差分) java
👵 改变数组元素

🧐 神之区间维护版
import java.util.*;
class Main{
static int T,n;
static int N = (int)2e5+10;
static int[] a = new int[N];
public static void main(String[] ars){
Scanner sc = new Scanner(System.in);
T = sc.nextInt();
while((T--)!=0)
{
n = sc.nextInt();
for(int i = 1; i <= n; i++){
a[i] = sc.nextInt();
}
int l = N;
for(int i = n; i >= 1; i--)
{
l = Math.min(l,i-a[i]+1);//更新边界
if(l <= i) a[i] = 1;//在区间内就更新元素
}
for(int i =1; i <= n; i++)
System.out.print(a[i] + " ");
System.out.println();
}
}
}
👵 差分数组版
👍 大佬详解版
import java.util.*;
class Main{
static int N = (int) 2e5 + 10;
static int n;
static int[] b = new int[N];// 差分数组
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
int T = sc.nextInt();
while (T-- != 0)
{
n = sc.nextInt();
Arrays.fill(b,0);
for (int i = 1; i <= n; i++)
{
int a = sc.nextInt();
int l = Math.max(1, i - a + 1);// 区间左端点,max函数防止越界
int r = i;// 区间右端点
// 差分本差:
// 左端点 +1,右端点 -1,相当于区间内的前缀和都 +1
// 此场景种,把输入的数据当成前缀和的数 ,数组存的是差分后的 每个元素
b[l]++;
b[r + 1]--;
}
for(int i = 1; i <= n; i++)
{
b[i] += b[i-1];//现在 b存的又是前缀和了
int k = b[i]!=0?1:0;//只要b[i]不为0,就是经过了0转1的情况
System.out.print(k+" ");
}
System.out.println();
}
}
}
👵 区间合并版
👵 参考连接
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef pair<int,int> PII;
const int N=200010;
PII range[N]; // 存储更新区间
int a[N]; // 存储答案数组
int main()
{
int t;
cin>>t;
while(t--)
{
int n,cnt=0; // cnt表示区间个数
cin>>n;
memset(a,0,(n+1)*4); // 清空答案数组前n+1个数
for(int i=1;i<=n;i++)
{
int x;
cin>>x;
if(x>0) // 如果需要更改区间
{
int l=max(1,i-x+1),r=i;
range[cnt++]={l,r};
}
}
sort(range,range+cnt); // 排序
int st=0,ed=0; // 维护区间左右端点
for(int i=0;i<cnt;i++) // 区间合并模板
{
if(range[i].first>ed) // 新维护区间
{
for(int j=st;j<=ed;j++) a[j]=1; // 将维护区间变为1
st=range[i].first,ed=range[i].second; // 新维护区间
}
else ed=max(range[i].second,ed); // 更新维护区间
}
for(int j=st;j<=ed;j++) a[j]=1; // 将最后一个维护区间变为1
for(int i=1;i<=n;i++) cout<<a[i]<<' '; // 输出答案数组
cout<<endl;
}
return 0;
}
😋 常数优化
① 标记流优化了 0.2 秒
② 数组按需初始化优化了 0.2 秒
static int N = (int) 2e5 + 10;
static int n;
static int[] b = new int[N];// 差分数组
public static void main(String[] args) throws IOException
{
// Scanner sc = new Scanner(System.in);
// 标记流输入,快 0.2 秒左右
StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
in.nextToken();
int T = (int) in.nval;
// int T = sc.nextInt();
while (T-- != 0)
{
// n = sc.nextInt();
in.nextToken();
n = (int) in.nval;
// Arrays.fill(b, 0);
// 由于不是每组数据都会用到 数组的所有空间,所以初始化需要用的空间即可
for (int i = 0; i <= n + 1; i++)
{
b[i] = 0;
}
for (int i = 1; i <= n; i++)
{
// int a = sc.nextInt();
in.nextToken();
int a = (int) in.nval;
int l = Math.max(1, i - a + 1);// 区间左端点,max函数防止越界
int r = i;// 区间右端点
// 差分本差:
// 左端点 +1,右端点 -1,相当于区间内的前缀和都 +1 【关键:前缀和才是 结果】
// 此场景种,把输入的数据当成前缀和的数 ,数组存的是差分后的 每个元素
b[l]++;
b[r + 1]--;
}
for (int i = 1; i <= n; i++)
{
b[i] += b[i - 1];// 现在 b存的又是前缀和了
int k = b[i] != 0 ? 1 : 0;
System.out.print(k + " ");
}
System.out.println();
}
}

👨🏫 Arrays.fill (数组,初始下标,末尾下标(排除),初始化的值);

浙公网安备 33010602011771号