POJ 3067 Japan【树状数组】

       这道题和那道Star如出一辙,有K条连接东西两个城市的路,东西方向每个城市都有一个编号M,N,从北到南,最后问共有多少个十字路都,即有多少个交点。
       先预处理,用结构体表示每条边,对结构体按N进行从小到大的排序,如果N相同,按M从小到大排序。接下来就和Star一样了,唯一不同的是Star那道题是每次求出当前星星前边的个数,而这个是求当前点后边的个数。用c[]表示树状数组,sum(n)求出的是N编号小于等于n的city的个数,只需每次拿出一个city,求出N编号大于它的city的个数,然后更新数组就可以了。

#include <cstdio> #include <cstring> #include <algorithm> #define MAX 10005 //最大的city个数 using namespace std; int c[MAX],n,N,M,K,omax; struct road { int west,east; }a[MAX*MAX]; //MAX*MAX为最多的边的个数 bool cmp(road a,road b){ if(a.west==b.west) return a.east<b.east; return a.west<b.west; } int lowbit(int t){ return t&(t^(t-1)); } int sum(int t){ int total=0;while(t>0){ total+=c[t]; t-=lowbit(t); } return total; } void modify(int posi,int key){ while(posi<=omax){ c[posi]+=key; posi+=lowbit(posi); } } int main() { int i,j,k,m,cas; long long ans; scanf("%d",&cas); for(i=1;i<=cas;++i){ omax=0; //用omax表示所有east的最大值,以确定求和区间 memset(c,0,sizeof(c)); scanf("%d%d%d",&N,&M,&K); for(j=1;j<=K;++j){ scanf("%d%d",&a[j].east,&a[j].west); if(a[j].east>omax) omax=a[j].east; } sort(a+1,a+1+K,cmp); ans=0; for(j=1;j<=K;++j){ //key code ans+=(sum(omax)-sum(a[j].east)); modify(a[j].east,1); } printf("Test case %d: %lld/n",i,ans); } } 

你可能感兴趣的:(c)