标签:cout oid ext 计算 const dash and final fine
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 29295 | Accepted: 7902 |
Description
Input
Output
Sample Input
1 3 4 4 1 4 2 3 3 2 3 1
Sample Output
Test case 1: 5
看似是一道二分图图论的问题,其实经过一些简单的(大雾)变换之后,就可以转化为树状数组来求解
自昨天被辉大神教做人之后,我对树状数组的理解也有了一些加深:0
大体题意:日本有东和西两个岛,从北到南依次标号为1,2,3...然后给出k条边,求出k条边一共有多少交点(注意是两两相交,只要两条线有交点就算一个)。
经过分析之后可以发现如果两条边有交点,就必须满足x1-x2>0&&y1-y2<0或者x1-x2<0&&y1-y2>0;
有两个条件,所以我们可以通过将x排序来变为一个条件:即将所有边按x的大小从小到大排序,然后一边遍历,一边维护树状数组。对于边k,在边1到边k-1中寻找y>yk的边,有几条这样的边,那么对于边k,在1~k-1中就有几个与之相交的边。
一边维护树状数组,一边更新交点的值,遍历结束后就可求出所有交点的数量。
PS:在排序时,如果x1==x2,那么要按y1<y2的顺序来排,不然在计算与较小y值那条边相交边的数量时,会将x与之相等的边也算进去(因为树状数组只存储y的值)。
#include<iostream> #include<cstdio> #include<vector> #include<set> #include<map> #include<string.h> #include<cmath> #include<algorithm> #include<queue> #define LL long long #define inf 0x3f3f3f3f using namespace std; int n,m,k; struct de { int x,y; bool operator<(const de &other)const { if(x==other.x) return y<other.y; return x<other.x; } }; de qiao[500*1010]; LL run[10100]={0}; int lowbit(int i){return i&(-i);} void update(int i) { while(i<=m) { run[i]++; i+=lowbit(i); } } LL sum(int i) { LL s=0; while(i>0) { s+=run[i]; i-=lowbit(i); } return s; } int main() { int t; scanf("%d",&t); for(int p=1;p<=t;p++) { scanf("%d%d%d",&n,&m,&k); memset(qiao,0,sizeof(qiao)); memset(run,0,sizeof(run)); for(int i=1;i<=k;i++) scanf("%d%d",&qiao[i].x,&qiao[i].y); sort(qiao+1,qiao+1+k); LL ans=0; for(int i=1;i<=k;i++) { ans+=sum(m)-sum(qiao[i].y); update(qiao[i].y); //cout << "ans=" << ans << endl; } printf("Test case %d: %I64d\n",p,ans); } return 0; }
标签:cout oid ext 计算 const dash and final fine
原文地址:http://www.cnblogs.com/brotherHaiNo1/p/7309154.html