UVALive 4329 树状数组第二题
大白书上的题目,比较巧妙的是其分析,为了求某个i点做裁判的时候的情况数,只要知道左边有多少比它小的记为ansc,右边有多少比它小的记为ansd,则总种数,必定为
ansc*(右边总数-ansd)+ansd*(左边总数-ansc)。
为了速度求出ansc和ansd,用到树状数组,这倒不是很难得地方,每次读到a[i],更新a[i]值+1即可。反过来求一次即可求出来 ansd
注意最后数据可能超过32位整数,因此用long long
树状数组的使用还有些不熟练。。。要继续加强
#include <iostream> #include <cstdio> #include <cstring> using namespace std; int x[100005]; long long n,a[20010],c[100010]; long long ansc[20010],ansd[20010]; int lowbit(int q) { return q&(-q); } long long sum(int q) { long long ret=0; while (q>0) { ret+=c[q]; q-=lowbit(q); } return ret; } void add(int loc,int d,int maxn) { while (loc<=maxn) { c[loc]+=d; loc+=lowbit(loc); } } int main() { int t; scanf("%d",&t); long long maxn=0; while (t--) { scanf("%lld",&n); for (int i=1;i<=n;i++){ scanf("%lld",&a[i]); maxn=max(maxn,a[i]); } memset(c,0,sizeof c); for (long long i=1;i<=n;i++) { //x[a[i]]=1; add(a[i],1,maxn); ansc[i]=sum(a[i]-1); } memset(c,0,sizeof c); for (long long i=n;i>=1;i--) { //x[a[i]]=1; add(a[i],1,maxn); ansd[i]=sum(a[i]-1); } long long ans=0; for (long long i=1;i<=n;i++) { ans+=ansc[i]*(n-i-ansd[i])+ansd[i]*(i-ansc[i]-1); } printf("%lld\n",ans); } return 0; }
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步