关于二维偏序的题
来源:互联网 发布:房地产 知乎 编辑:程序博客网 时间:2024/05/16 23:55
简单的逆序对
可以用树状数组搞
就是插入时,找前面比他大的和
插入时弄一个桶,记下有多少个数
然后对后面的进行区间求和,这个可以用树状数组搞
最后求一个总和
#include<iostream>#include<queue>#include<algorithm>#include<cstdio>using namespace std;int n,a[49999],sum[4999999],max1;int add(int x,int w){ for(int i=x;i>0;i-=i&(-i)) sum[i]+=w;}int chaxun(int x){ int ans=0; for(int i=x;i<=max1;i+=i&(-i)) ans+=sum[i]; return ans;}int main(){ int ans=0; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); add(a[i],1); max1=max(a[i],max1); ans+=chaxun(a[i]); } printf("%d",ans-n);}
难一点的
三元逆序对
这样的话就可以枚举一个位置,找前面比他大的,和后面比他小的,乘起来,统计和
#include<iostream>#include<queue>#include<algorithm>#include<cstdio>using namespace std;int n,a[49999],sum[4999999],max1,sum2[4419999];int add(int x,int w){ for(int i=x;i<=max1;i+=i&(-i)) sum[i]+=w;}int chaxun(int x){ int ans=0; for(int i=x-1;i>0;i-=i&(-i)) ans+=sum[i]; return ans;}int add2(int x,int w){for(int i=x;i>0;i-=i&(-i)) sum2[i]+=w; }int chaxun2(int x){ int ans=0; for(int i=x+1;i<=max1;i+=i&(-i)) ans+=sum2[i]; return ans;}int main(){ long long ans=0; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a[i]);max1=max(a[i],max1); add2(a[i],1); } for(int i=1;i<=n;i++) { add(a[i],1);add2(a[i],-1); //printf("%d %d",chaxun(a[i]),chaxun2(a[i])); ans+=1ll*chaxun2(a[i])*chaxun(a[i]); } printf("%lld",ans);}
这个题有一点难度
需要你转化思想
你知道这个题就是求一个和,暴力n^2可以完成,但一定过不了
所以就需要一些优化
像上面这样,从小到大枚举v,之前的一定比他小直接统计就行了,但有个很麻烦的绝对值。。。
那你就维护两个和,一个是小的一个是大的,这个可以轻易的用树状数组维护,这样就把绝对值去了
代码:
#include<cstdio>#include<queue>#include<cstring>#include<iostream>#include<algorithm>#define ll long longusing namespace std;ll n;ll s,ans;struct st{ ll v,x;}p[299099];ll maxn,sum[299099],tot[299099],sum2[299099],tot2[290999];ll cmp(const st &a,const st &b){ if(a.v<b.v||a.v==b.v&&a.x<b.x) return 1; return 0;}ll add(ll x,ll w,ll w2)//前缀 { for(ll i=x;i<=maxn;i+=i&-i) sum[i]+=w,tot[i]+=w2;}ll cx(ll x){ ans=0,s=0; for(ll i=x;i>0;i-=i&-i) ans+=sum[i],s+=tot[i];}ll add2(ll x,ll w,ll w2)//后缀 { for(ll i=x;i>0;i-=i&-i) sum2[i]+=w,tot2[i]+=w2;}ll cx2(ll x){ ans=0,s=0; for(ll i=x+1;i<=maxn;i+=i&-i) ans+=sum2[i],s+=tot2[i];}int main(){ scanf("%lld",&n); for(ll i=1;i<=n;i++) scanf("%lld%lld",&p[i].v,&p[i].x),maxn=max(maxn,p[i].x);; sort(p+1,p+n+1,cmp); ll ss=0; for(ll i=1;i<=n;i++) { ll sss=0; add(p[i].x,1,p[i].x); add2(p[i].x,1,p[i].x); cx(p[i].x); sss+=(ans*p[i].x-s); cx2(p[i].x); sss+=(s-ans*p[i].x); sss*=p[i].v; ss+=sss; } printf("%lld",ss);}
阅读全文
1 0
- 关于二维偏序的题
- 关于二维指针的代码
- 关于二维数组的感想
- 关于二维数组的理解
- 关于二维数组和二维指针的相关问题
- 关于二维数组和二维指针的理解总结
- 关于二维条码技术的思考 开篇
- 关于二维数组指针的问题?
- 关于二维数组的动态分配空间
- 关于二维浮点型数组的问题
- 关于二维指针的一个用处
- 一道关于C++二维数组的问题
- 关于二维数组做参数的问题
- 关于vector定义二维数组的问题
- 关于python二维数组的声明
- 关于js中二维数据的定义
- 关于C++二维数组的返回问题
- 关于动态new二维数组的问题
- 逆序对
- UVa 10912
- 【C语言】数组
- 经济生活知识
- MySQL中的锁(表锁、行锁,共享锁,排它锁,间隙锁)
- 关于二维偏序的题
- 几种编码区别
- vs2012 error LNK2038 RuntimeLibrary 不匹配的解决
- HDU 1546 Idiomatic Phrases Game
- HttpClient学习整理
- ToolBar的使用
- Android实现简单的纸飞机操作(类似于漂流瓶)
- zeros and ones (找规律)
- docker 部署 shipyard