题意:给出一个长度为n的序列,构造k(1<=k<n)叉小根堆,规定点i的父亲是(i-2)/k+1,问k叉堆中有多少个点不符合要求。
哎呀,这题很好做嘛。。你看数据是10W,然后看到(i-2)/k+1,因为整除嘛。。最多有sqrt(i-2)种取值(是吧我没说错吧?),连续一段答案会是相等的,也就是说,对于一段k在k·~(i-2)/((i-2)/k·)范围内,一个点的父亲都是同一个点QAQ。于是复杂度就是n*sqrt(n)啦。涉及到区间修改单点查询,就用差分求前缀和优化一下就好啦~哎呀这样就做出来了0.0。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define INF 0x3f3f3f3f #define ll long long #define N 200020 using namespace std; int data[N],n; int sum[N]; int main(){ scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&data[i]); } for(int i=2;i<=n;i++){ int v=i-2; int j,t; for(j=1;j<=i-2;j=t+1){ t=v/(v/j); if(data[(i-2)/j+1]>data[i]) sum[j]++,sum[t+1]--; } if(data[1]>data[i]) sum[i-1]++,sum[n]--; } for(int i=1;i<n;i++){ sum[i]+=sum[i-1]; printf("%d ",sum[i]); } return 0; }