想去日本修路吗?点击这里
Japan
| Time Limit: 1000MS | Memory Limit: 65536K | |
| Total Submissions: 35534 | Accepted: 9511 |
Description
Japan plans to welcome the ACM ICPC World Finals and a lot of roads must be built for the venue. Japan is tall island with N cities on the East coast and M cities on the West coast (M <= 1000, N <= 1000). K superhighways will be build. Cities on each coast are numbered 1, 2, ... from North to South. Each superhighway is straight line and connects city on the East coast with city of the West coast. The funding for the construction is guaranteed by ACM. A major portion of the sum is determined by the number of crossings between superhighways. At most two superhighways cross at one location. Write a program that calculates the number of the crossings between superhighways.
Input
The input file starts with T - the number of test cases. Each test case starts with three numbers – N, M, K. Each of the next K lines contains two numbers – the numbers of cities connected by the superhighway. The first one is the number of the city on the East coast and second one is the number of the city of the West coast.
Output
For each test case write one line on the standard output:
Test case (case number): (number of crossings)
Sample Input
1
3 4 4
1 4
2 3
3 2
3 1
Sample Output
Test case 1: 5
当你来到日本后
告诉你日本东海岸有几个城市,西海岸有几个城市,再告诉你一些道路的两个端点,并且最多两条公路在同一地点交叉。。。。日本人真是种奇怪的生物,修个公路还那么讲究,然后再来让ACMer来受罪
问你 所给的这些公路的交点有几个?
我就在那画啊画,也没画出来什么道道,直到测试结束了才知道这是个求逆序对的问题。那么为什么是逆序对呢?其实你想啊,两条道路怎么才会相交呢?肯定是两条道路的起点大小关系和终点的大小关系不一样,这样才会相交。刚好这就是逆序对啊,我怎么就没想到呢?光在那里画拉玩了 卑微 Orz
那么怎么解呢?先将道路按照起点或者终点排序(排完序就看出是逆序对了吧)然后就是树状数组求逆序对的板子了
#define ll long long
ll res=0;
可以有这三种写法
//...1...
for(int i=1;i<=way;i++){
up(pp[i].r,1);
res+=i-sum(pp[i].r);
}
//...2...
for(int i=0;i<way;i++){
res+=i-sum(pp[i].r);
up(pp[i].r,1);
}
//...3...
for(int i=0;i<way;i++){
up(pp[i].r,1);
res+=(sum(m)-sum(pp[i].r));
}
下面侍者道题的AC代码 太卑微了
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define ll long long
using namespace std;
const ll mm=1005;
ll n,m,way;
ll c[mm];
struct node{
ll l,r;
}pp[mm*mm];
bool cmp(node a,node b){
if(a.l==b.l)
return a.r<b.r;
return a.l<b.l;
}
ll lbt(ll x){
return x&-x;
}
void up(ll pos,ll k){
while(pos<=mm){
c[pos]+=k;
pos+=lbt(pos);
}
}
ll sum(ll pos){
ll res=0;
while(pos>0){
res+=c[pos];
pos-=lbt(pos);
}
return res;
}
int main()
{
ll t;
ll test=1;
scanf("%lld",&t);
while(t--){
memset(c,0,sizeof(c));
scanf("%lld%lld%lld",&n,&m,&way);
for(int i=1;i<=way;i++)
scanf("%lld%lld",&pp[i].l,&pp[i].r);
sort(pp+1,pp+way+1,cmp);
ll res=0;
// for(int i=0;i<way;i++){
// up(pp[i].r,1);
// res+=(sum(m)-sum(pp[i].r));
// }
for(int i=1;i<=way;i++){
up(pp[i].r,1);
res+=i-sum(pp[i].r);
}
printf("Test case %lld: %lld\n",test++,res);
}
return 0;
}
本文介绍了一道关于在日本修路的算法题目,涉及到计算不同城市间修建的超级高速公路之间的交叉点数量。通过将问题转化为求逆序对,利用树状数组进行高效计算,最终解决了这一复杂的计数问题。
413

被折叠的 条评论
为什么被折叠?



