牛客多校第九场D(二维差分,树状数组)
1:题意:
找出所有的区间x,x里面的数的位置k不能是第k小
2:思路
对于一个确定的数字 ,考虑对于区间 ,如果这个 导致了区间不合法,那一定是它是这个区间的第 小。考虑 左侧比 大的个数,和 右侧比 小的数字个数,显然这两个要相等,及找出左大等于右小的个数,找出所有不合法的区间合并剩下的就是答案
3:二维差分
点击查看代码
#include <bits/stdc++.h>
using namespace std;
const int N = 5e3+10;
int a[N];
vector<int>x[N],y[N];
int f[N][N];
void solve()
{
int n;
std::cin >> n;
for(int i = 1;i <= n;i ++)
std::cin >> a[i];
for(int i = 1;i <= n;i ++)
{
int big = 0,small = 0;
for(int j = i;j <= n;j ++)//右小
{
if(a[j]<a[i])
small++;
y[small].push_back(j);
}
for(int j = i;j>=1 ;j --)//左大
{
if(a[j] > a[i])
big++;
x[big].push_back(j);
}
for(int j = 0;j <= n;j ++)
{
if(x[j].size()!=0&&y[j].size()!=0)
{
f[x[j].back()][y[j].front()]++;//左下角
f[x[j].back()][y[j].back()+1]--;
f[x[j].front()+1][y[j].front()]--;
f[x[j].front()+1][y[j].back()+1]++;//右上角
}
x[j].clear(),y[j].clear();
}
}
for(int i = 1;i <= n;i ++)
{
for(int j = 1;j <= n;j ++)
{
f[i][j] = f[i][j] + f[i-1][j] + f[i][j-1] - f[i-1][j-1];
}
}
int ans = 0;
for(int i = 1;i <= n;i ++)
for(int j = i;j <= n;j ++)
if(f[i][j] == 0)
ans++;
for(int i = 0;i <= n+1;i ++)
for(int j = 0;j <= n+1;j ++)
f[i][j] = 0;
std::cout << ans << '\n';
}
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
int t;
std::cin >> t;
while(t--)
solve();
}
4:树状数组
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=5005;
int T;
int n,a[N],pos[N][N],res,v[N],dp[N];
int lowbit(int x){
return x&(-x);
}
void add(int x,int v){
for(int i=x;i<=n;i+=lowbit(i))
dp[i]+=v;
}
int ask(int x){
int tot=0;
for(int i=x;i;i-=lowbit(i))
tot+=dp[i];
return tot;
}
void solve(){
res=0;
cin>>n;
for(int i=1;i<=n;i++) v[i]=0;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++)
for(int j=0;j<=n;j++)
pos[i][j]=0;
for(int i=1;i<=n;i++){
int cnt=0;
pos[i][cnt]=i;
for(int j=i+1;j<=n;j++){
if(a[j]<a[i]){
cnt++;
pos[i][cnt]=j;
// cout<<i<<" "<<cnt<<" "<<j<<endl;
}
}
pos[i][cnt+1]=n+1;
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++) dp[j]=v[j]=0;
for(int j=i;j<=n;j++){
add(a[j],1);
int num=ask(a[j]-1);
int rank=j-i+1;
int l=pos[j][rank-num-1];
int r=pos[j][rank-num]-1;
v[l]++;
v[r+1]--;
}
int sum=0;
for(int j=i;j<=n;j++){
sum+=v[j];
if(!sum) res++;//,cout<<i<<" "<<j<<endl;;
}
}
cout<<res<<endl;
}
int main(){
cin>>T;
while(T--) solve();
return 0;
}