我一开始的思路:
这个思路只能拿40分,设下的全部超时(因为本质是枚举啊)
因为每个点显然只可能在某⼀个翻转中⼼才可能变成不动点。
我们枚举每个翻转中⼼。接下来要考虑的是⻓度的东⻄。如果我们这个翻转的东⻄包括了某个之前就是不动点的点,那么翻转之后那么这个不动点就不是不动点了。
实际的思路:
因为所有可能的答案只有恰好包住了某个翻转之后会变成不动点的这些区间,显然这些区间的个数总和是O(n)的。⽽我们要知道某个区间翻转后的不动点个数也是O(1)的(每次可以知道这⾥⾯包含了多少个会变成不动点的点,然后再来⼀个前缀和可以知道会让多少个原来是不动点的变成不是不动点)。
40分的:
#include<bits/stdc++.h>
using namespace std;
long long n,k,ans,g[1000],h[1000],f[1000],Next[1000][1000],top[1000];
inline void search(long long now,long long w)
{
w+=g[now];
if(w>=k)
{
ans+=f[now];
return;
}
for(int i=1;i<=top[now];i++)
search(Next[now][i],w);
}
int main()
{
cin>>n>>k;
for(int i=1;i<=n;i++)
cin>>h[i]>>g[i];
for(int i=1;i<=n;i++)
for(long long j=i+1;j<=n;j++)
if(h[j]>h[i])
Next[i][++top[i]]=j;
f[n]=1;
for(int i=n-1;i>=1;i--)
{
f[i]=1;
for(int j=i+1;j<=n;j++)
if(h[j]>h[i])
f[i]+=f[j];
}
for(int i=1;i<=n;i++)
search(i,0);
cout<<ans;
return 0;
}
100分的:
#include<bits/stdc++.h>
using namespace std;
const int lim=1<<21;
long long Sum1[41][lim];
long long Sum2[41][lim];
int state1[41];
int state2[41];
int n;
long long k;
int mid;
long long ans;
int f[41];
int h[41];
int a[41];
int g[41];
void dfs1(int start,int now,long long sum)
{
Sum1[start][++state1[start]]=sum;
if(Sum1[start][state1[start]]>=k)
{
ans++;
}
for(int i=now-1;i>=1;--i)
{
if(h[now]>=h[i])
{
dfs1(start,i,sum+a[i]);
}
}
}
void dfs2(int start,int now,long long sum)
{
Sum2[start][++state2[start]]=sum;
if(Sum2[start][state2[start]]>=k)
{
ans++;
}
for(int i=now+1;i<=n;++i)
{
if(h[now]<=h[i])
{
dfs2(start,i,sum+a[i]);
}
}
}
void init()
{
f[1]=1;
g[n]=1;
for(int i=1;i<=mid;++i)
{
f[i]=1;
for(int j=1;j<=i;++j)
{
if(h[i]>=h[j])
{
f[i]+=f[j];
}
}
}
for(int i=n;i>=mid+1;--i)
{
g[i]=1;
for(int j=i+1;j<=n;++j)
{
if(h[i]<=h[j])
{
g[i]+=g[j];
}
}
}
}
signed main()
{
ios::sync_with_stdio(false);
cin>>n>>k;
mid=n>>1;
for(int i=1;i<=n;++i)
{
cin>>h[i]>>a[i];
}
for(int i=1;i<=mid;++i)
{
dfs1(i,i,a[i]);
}
for(int i=mid+1;i<=n;++i)
{
dfs2(i,i,a[i]);
}
for(int i=1;i<=mid;++i)
{
sort(Sum1[i]+1,Sum1[i]+state1[i]+1);
}
for(int i=mid+1;i<=n;++i)
{
sort(Sum2[i]+1,Sum2[i]+state2[i]+1);
}
for(int i=1;i<=mid;++i)
{
for(int j=mid+1;j<=n;++j)
{
if(h[i]>h[j])
continue;
for(int l=1;l<=state1[i];++l)
{
long long res=k-Sum1[i][l];
int pos=lower_bound(Sum2[j]+1,Sum2[j]+state2[j]+1,k-Sum1[i][l])-Sum2[j];
if(pos==state2[j]+1)
continue;
ans+=state2[j]-pos+1;
}
}
}
cout<<ans<<endl;
return 0;
}