poj 3067 Japan 树状数组求逆序对
2016-07-06 19:53
447 查看
传送门
题目大意:
给出t个case,每个case给出k条边,这些边的左右两个端点分别属于n和m两个集合,求出有多少条相交的边(如果两条边有公共端点不算相交)
分析:
显然如果两条边相交一定满足(xi-xj)*(yi-yj)<0,所以我们可以把k条边按照x单调递增的顺序排排序,然后求y的逆序对即可(注意:如果两条边x相同,y按照递增的顺序排,因为这样处理时不会把这两条边算为相交的边Notice!!!)
代码如下:
by >o< neighthorn
题目大意:
给出t个case,每个case给出k条边,这些边的左右两个端点分别属于n和m两个集合,求出有多少条相交的边(如果两条边有公共端点不算相交)
分析:
显然如果两条边相交一定满足(xi-xj)*(yi-yj)<0,所以我们可以把k条边按照x单调递增的顺序排排序,然后求y的逆序对即可(注意:如果两条边x相同,y按照递增的顺序排,因为这样处理时不会把这两条边算为相交的边Notice!!!)
代码如下:
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #define LL long long using namespace std; const int maxn=1000+5; int cas,n,m,k,t; LL tr[maxn],ans,ONE=1; struct road{ int x,y; }s[maxn*maxn]; bool cmp(road a,road b){ if(a.x==b.x) return a.y<b.y; return a.x<b.x; } void add(int x,LL y){ for(;x<=m;x+=(x&(-x))) tr[x]+=y; } LL query(int x){ LL sum=0; for(;x;x-=(x&(-x))) sum+=tr[x]; return sum; } signed main(void){ scanf("%d",&cas),t=0; while(cas--){ scanf("%d%d%d",&n,&m,&k); for(int i=1;i<=k;i++) scanf("%d%d",&s[i].x,&s[i].y); sort(s+1,s+k+1,cmp); ans=0,memset(tr,0,sizeof(tr)); for(int i=1;i<=k;i++) add(s[i].y,ONE),ans+=query(m)-query(s[i].y); t++; printf("Test case %d: %lld\n",t,ans); } return 0; }
by >o< neighthorn
相关文章推荐
- HTML标记语言介绍
- 5-15 计算圆周率 (15分)
- css3图片翻转功能的实现
- 普里姆算法(Prim)和克鲁斯卡尔(Kruskal)算法
- 119. Pascal's Triangle II
- quagga安装配置
- [改善Java代码]不同的列表选择不同的遍历方法
- hibernate懒加载
- 剑指offer-3-面试16:反转链表
- 1017. Queueing at Bank (25)
- 静态方法块 static 以及对象属性&类属性的用法
- opencv报错
- 关于quartz可以设置为串行执行的比较详细说明
- 7款Java反编译工具
- GNU Autotools的使用方法
- FPGA DDR3调试
- 网购
- setTimeout
- hibernate多对多关联
- [bzoj 3124][sdoi 2013 省选] 直径