题意: 有n个人 每个人有其一开始所在的位置 有m个询问 l r k 问编号为l到r的人填满区间 k----k+r-l 需要的最少距离
很容易发现按照原来的相对位置来填k开始的位置肯定是一种最优解
lr的编号区间很容易想到主席树
所以问题转化为如何优化主席树的询问
1、如果遍历每个人 然后累和每个人的距离 肯定会超时 复杂度接近on
2、可以分三种情况讨论
如果所有的人都在 应到位置的左边 那么贡献为
如果所有的人都在 应到位置的右边 那么贡献为
否则的话递归到子树继续进行分类
学会了主席树一种新的查询方式!!!
#include<bits/stdc++.h> using namespace std; #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i>=(b);--i) #define ll long long #define see(x) (cerr<<(#x)<<'='<<(x)<<endl) #define pb push_back #define inf 0x3f3f3f3f #define CLR(A,v) memset(A,v,sizeof A) typedef pair<int,int>pii; ////////////////////////////////// const int N=1e6+10; int T[N],lson[N<<5],rson[N<<5],ncnt,n,m; ll t[N<<5],sum[N<<5]; void upnode(int x,int l,int r,int pre,int &pos) { pos=++ncnt; lson[pos]=lson[pre];rson[pos]=rson[pre]; t[pos]=t[pre]+1; sum[pos]=sum[pre]+x; int m=(l+r)>>1; if(l==r)return ; if(x<=m)upnode(x,l,m,lson[pre],lson[pos]); else upnode(x,m+1,r,rson[pre],rson[pos]); } ll qsum(int L,int R,int l,int r,int pre,int pos) { if(L>R)return 0; if(r<=L)return 1ll*(L+R)*(R-L+1)/2-(sum[pos]-sum[pre]); if(l>=R)return (sum[pos]-sum[pre])-1ll*(L+R)*(R-L+1)/2; if(l==r)return 0;int m=(l+r)>>1; int peo=t[lson[pos]]-t[lson[pre]]; return qsum(L,L+peo-1,l,m,lson[pre],lson[pos])+qsum(L+peo,R,m+1,r,rson[pre],rson[pos]); } int main() { scanf("%d%d",&n,&m);int x; rep(i,1,n)scanf("%d",&x),upnode(x,1,1e6,T[i-1],T[i]); int l,r,k; while(m--) { scanf("%d%d%d",&l,&r,&k); printf("%lld\n",qsum(k,k+r-l,1,1e6,T[l-1],T[r])); } return 0; }