水题
class Solution {
public:
int countOdds(int low, int high) {
if(low%2==0 && high%2==0)
return (high-low)/2;
return (high-low)/2+1;
}
};
算一下前缀和遍历一遍就好了,水题
long long mod = 1e9 + 7;
class Solution {
public:
long long numOfSubarrays(vector<int>& arr) {
int n = arr.size();
vector<long long> sum(n+1);
sum[0] = arr[0];
for(int i=1;i<n;++i)
sum[i] = sum[i-1]+arr[i];
int js=0;
long long ans = 0;
int os = 0;
for(int i=0;i<n;++i)
{
if(sum[i]&1)
{
ans=(ans+i-js+mod+1ll)%mod;
js++;
}
else
ans=(ans+js)%mod;
//cout<
}
return ans;
}
};
维护一个前缀,维护一个后缀然后遍历一下就好,水题
int l[100010],r[100010];
int zm[30];
class Solution {
public:
int numSplits(string s) {
for(int i=0;i<s.length()+3;++i)
l[i]=r[i]=0;
for(int i=0;i<30;++i)
zm[i] = 0;
for(int i=0;i<s.length();++i)
if(zm[s[i]-'a']==0)
{
l[i+1] = l[i]+1;
zm[s[i]-'a']=1;
}
else
l[i+1]=l[i];
for(int i=0;i<30;++i)
zm[i] = 0;
for(int i=s.length()-1;i>=0;--i)
if(zm[s[i]-'a']==0)
{
r[i+1] = r[i+2]+1;
zm[s[i]-'a']=1;
}
else
r[i+1] = r[i+2];
int ans = 0;
for(int i=1;i<s.length();++i)
if(l[i]==r[i+1])
ans++;
return ans;
}
};
一眼就想用线段树了
思路:遍历数组,每次删除尽可能长的区间
我的写法:维护一个线段树,遍历数组每次寻找连续的最小的数的位置(连续指两个数之间没有0),然后这个连续区间整体减掉这个数字。
然后我写了个憨批有问题的代码,交了发现对了,然后就有了一个其他思路。
憨批代码:
const int N = 1e5+10;
class Solution {
public:
int segm[N<<3];
int arr[N];
int lazy[N<<3];
void build(int pos,int l,int r)
{
if(l==r)
{
segm[pos] = arr[l];
return;
}
int mid = l+r>>1;
build(pos<<1,l,mid);
build(pos<<1|1,mid+1,r);
segm[pos] = min(segm[pos<<1],segm[pos<<1|1]);
}
void pushdown(int pos)
{
segm[pos<<1] -= lazy[pos];
segm[pos<<1|1] -= lazy[pos];
lazy[pos<<1] += lazy[pos];
lazy[pos<<1|1] += lazy[pos];
lazy[pos] = 0;
}
void md(int pos,int l,int r,int d)
{
if(lazy[pos])
pushdown(pos);
if(l==r)
{
segm[pos] = (1<<30);
return;
}
int mid = l+r>>1;
if(d<=mid)
md(pos<<1,l,mid,d);
else
md(pos<<1|1,mid+1,r,d);
segm[pos] = min(segm[pos<<1],segm[pos<<1|1]);
}
void mdq(int pos,int l,int r,int L,int R,int x)
{
//cout<
if(lazy[pos])
pushdown(pos);
if(L<=l && r<=R)
{
segm[pos]-=x;
lazy[pos]+=x;
return;
}
int mid = (l+r)>>1;
if(L<=mid)
mdq(pos<<1,l,mid,L,R,x);
if(mid<R)
mdq(pos<<1|1,mid+1,r,L,R,x);
segm[pos] = min(segm[pos<<1],segm[pos<<1|1]);
}
int find(int pos,int l,int r,int &dd)
{
if(lazy[pos])
pushdown(pos);
if(l==r)
{
dd = segm[pos];
return l;
}
int mid = l+r>>1;
//cout<
if(segm[pos<<1]<=segm[pos<<1|1])
return find(pos<<1,l,mid,dd);
else
return find(pos<<1|1,mid+1,r,dd);
segm[pos] = min(segm[pos<<1],segm[pos<<1|1]);
}
int findd(int pos,int l,int r,int d)
{
//cout<
if(lazy[pos])
pushdown(pos);
if(l==r)
return segm[pos];
int mid = (l+r)>>1;
if(d<=mid)
return findd(pos<<1,l,mid,d);
else
return findd(pos<<1|1,mid+1,r,d);
segm[pos] = min(segm[pos<<1],segm[pos<<1|1]);
}
int minNumberOperations(vector<int>& target) {
for(int i=0;i<target.size();++i)
arr[i+1] = target[i];
int n = target.size();
build(1,1,n);
int ans = 0;
for(int i=1;i<=n;++i)
{
while(1)
{
int dd;
int xb = find(1,1,n,dd);
if(dd==0)
{
if(xb==i)
break;
xb--;
int e = findd(1,1,n,xb);
ans += e;
mdq(1,1,n,i,xb,e);
}
else
{
ans += dd;
mdq(1,1,n,i,n,dd);
}
}
md(1,1,n,i);
}
return ans;
}
};
真正的解法
递增的就作差加上贡献,递减的不用管
class Solution {
public:
int minNumberOperations(vector<int>& target) {
int ans = 0;
int d = 0;
for(int i:target)
{
int c = i-d;
if(c>=0)
{
ans+=c;
d+=c;
}
else
{
d = i;
}
}
return ans;
}
};
这个也写的很憨,其实可以这么写
class Solution {
public:
int minNumberOperations(vector<int>& target) {
int ans = target[0], n = target.size();;
for(int i=1;i<n;i++)
if(target[i] > target[i-1])
ans += target[i] - target[i-1];
return ans;
}
};