B - ARC Wrecker
题意:选取一个x,使得数组中所有大于x的数都减1,x能够多次选,问能够产生多少个不同的数组。
思路:最大的数减到与第二大数相同的大小的过程中都是新产生的数组,当与第二大相同时,第二大减到第三大的过程中产生的数组也全是新产生的数组,…,这样可以将数组从小到大排序,答案为(a[n]-a[n-1]+1)(a[n-1]-a[n-2]+1)…(a[1]-0+1)
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int a[100010];
const ll mod=1e9+7;
int main(){
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
sort(a+1,a+1+n);
ll k=1;
for(int i=n;i>=1;i--){
k=k*(a[i]-a[i-1]+1)%mod;
}
cout<<k<<endl;
return 0;
}
C - ARC Wrecker 2
https://atcoder.jp/contests/arc119/tasks/arc119_c
题意:对数组有两种操作
1.选取一个x,使得下标为x和x+1的点全部加1。
2.选取一个x,使得下标为x和x+1的点全部减1。
问可以选取多少个区间[l,r]使得区间所有值操作后都为0。
思路:下标为奇数是加到ans1,偶数时加到ans2,然后每次做减法得到k,res+=mp[k],然后mp[k]++,因为大于等于2次出现的k可以减去之前出现的k的区间,来使得该区间的值为0。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
map<ll,int>mp;
int main(){
mp[0]=1;
int n;
scanf("%d",&n);
ll ans1=0,ans2=0;
ll res=0;
for(int i=1;i<=n;i++){
int x;
scanf("%d",&x);
if(i&1)ans1+=x;
else ans2+=x;
ll k=ans1-ans2;
res+=mp[k];
mp[k]++;
}
printf("%lld\n",res);
return 0;
}