hdu5603the soldier of love
来源:互联网 发布:p身份证的软件 编辑:程序博客网 时间:2024/05/16 08:56
链接:http://acm.hdu.edu.cn/showproblem.php?pid=5603
题意:给你多组数据,每组数据第一行是一个n和m,表示的意义是n条线段和m组点。接下来是n条线段的左端点和右端点,m行每行第一个是这组点的个数Ki,接下来同一行有Ki个数表示点的位置。问题是求对于每组点来说,有多少条线段至少有一个该组上的点在线段上,输入m行。
分析:其实题目要求的问题,我们有一种很直接的错误的办法:将每条线段铺在数轴上,然后对于每组点的每个点来数一数有多少条线段经过这个点。很显然我们会重复计算经过多个点的线段,怎么办呢?其实我们只要将前面经过点的线段在后面的计算中去除就行啦。怎么去除呢?我们可以先将每一条线段的左右端点和每一组点的前后两个点当成一组点来存起来,然后排序,排序规则是线(L,R),点(前,后)按照"L"和"前"从小到大排序,“L”=“前"的时候"L"<”前“,这样我们将点和线排完之后。按排序顺序处理点和线段,(1)遇到线段时,我们将该线段的右端点插入到树状数组中。(2)遇到点时,我们将已经插入到树状数组中的右端点大于等于”前“的点的个数加入到ans[i]中,同时将右端点大于等于”后“的点的个数在ans[i]中减去。这样我们就将原来的那个错误的办法处理成正确的方法啦~时间复杂度是O((n+sum)*log10^6),sum=m组点的总个数。
代码:
#include<map>#include<set>#include<cmath>#include<queue>#include<math.h>#include<cstdio>#include<vector>#include<string>#include<cstring>#include<iostream>#include<algorithm>#pragma comment(linker, "/STACK:102400000,102400000")using namespace std;const int N=1000010;const int MAX=151;const int MOD=1000007;const int MOD1=100000007;const int MOD2=100000009;const int INF=1000000000;const double EPS=0.00000001;typedef long long ll;typedef unsigned long long ull;int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f;}int e[300010],ans[300010],f[N];struct node{ int a,b,c,d;}q[N];int cmd(node x,node y) { if (x.a!=y.a) return x.a<y.a; else return x.c<y.c;}void add(int x,int y) { for (;x<=1000000;x+=x&(-x)) f[x]+=y;}int get(int x) { int ret=0; for (;x;x-=x&(-x)) ret+=f[x]; return ret;}int main(){ int a,b,i,j,k,g,n,m; while (scanf("%d%d", &n, &m)!=EOF) { k=0; for (i=1;i<=n;i++) { scanf("%d%d", &a, &b); k++;q[k].a=a;q[k].b=b;q[k].c=0;q[k].d=0; } for (i=1;i<=m;i++) { scanf("%d", &g);e[g+1]=1000001; for (j=1;j<=g;j++) scanf("%d", &e[j]); for (j=1;j<=g;j++) { k++;q[k].a=e[j];q[k].b=e[j+1];q[k].c=1;q[k].d=i; } } sort(q+1,q+k+1,cmd); memset(f,0,sizeof(f)); memset(ans,0,sizeof(ans)); for (i=1;i<=k;i++) if (q[i].c) ans[q[i].d]+=get(q[i].b-1)-get(q[i].a-1); else add(q[i].b,1); for (i=1;i<=m;i++) printf("%d\n", ans[i]); } return 0;}
0 0
- hdu5603the soldier of love
- hdu 5603 the soldier of love
- HDU 5603 the soldier of love (线段树)
- HDU 5603/BC 67D the soldier of love
- HDU 5603 the soldier of love(BIT)
- soldier
- Soldier
- Soldier of Fortune II: Double Helix
- a story of love
- the code of love
- All out of love
- The science of love
- love of distress
- The love of programmer
- Game Theory Of Love
- for the love of god
- The Art of Love Letters
- love story of Isaac Newton
- 线程与进程的区别、联系
- 广点通 (iOS完整版)
- 【d3.js教程04】互动第一步
- C++ 统计一个类对象的个数
- iOS 中 AVAudioPlayer(专门用来播放本地音乐)
- hdu5603the soldier of love
- 网站文章阅读数缓存实现
- 标准IO与文件IO
- 学习网站
- Codeforces Round #333 (Div. 2) A. Two Bases (进制转换比较大小)
- 外语-服务-钱-见识
- Git 学习(1)
- remove duplicates from sorted Array
- Android中的文件上传下载