zoukankan      html  css  js  c++  java
  • 【CF1000C】Covered Points Count(离散化+差分)

    点此看题面

    大致题意: 给出(n)条线段,分别求有多少点被覆盖(1)次、(2)次...(n)次。

    正常的算法

    好吧,这道题目确实有个很简单的贪心做法(只可惜我做的时候没有想到,结果想了半天只想出一个无比麻烦的),这里介绍一个稍微有些复杂的。

    不正常的算法(我的算法)

    考虑离散化每一个出现过的点以及这些点后面的点(之所以要离散化这些后面的点,是为了方便后面的差分)。

    假如我们用(p[i])来表示原来为(i)的数离散化后的值,并用(q[i])表示离散化后值为(i)的数原来的值,则:

    对于一条线段,假设它的左端点为(l),右端点为(r),那么我们就将(f[p[l]])加1,并将(f[p[r+1]])减1(经典的差分套路),最后求出其前缀和,就可以求出每一块被覆盖的次数,从而将其还原计算出答案。

    代码

    #include<bits/stdc++.h>
    #define max(x,y) (x>y?x:y)
    #define min(x,y) (x<y?x:y)
    #define LL long long
    #define N 200000
    using namespace std;
    int n;
    LL x[N+5],y[N+5],z[4*N+5],f[4*N+5],ans[N+5];
    map<LL,LL> p,q;
    LL read()
    {
    	LL x=0,f=1;char ch=getchar();
    	while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    	if(ch=='-') f=-1,ch=getchar();
    	while(ch>='0'&&ch<='9') (x*=10)+=ch-'0',ch=getchar();
    	return x*=f;
    }
    void write(LL x)
    {
    	if(x<0) putchar('-'),x=-x;
    	if(x>9) write(x/10);
    	putchar(x%10+'0');
    }
    int main()
    {
    	n=read();
    	for(int i=1;i<=n;i++) z[4*i-3]=x[i]=read(),z[4*i-2]=x[i]+1,z[4*i-1]=y[i]=read(),z[4*i]=y[i]+1;
    	int w=4*n,k=0;
    	sort(z+1,z+w+1);
    	for(int i=1;i<=w;i++) if(z[i]!=z[i-1]||i==1) p[z[i]]=i-k,q[i-k]=z[i];else k++;//离散化
    	for(int i=1;i<=n;i++) f[p[x[i]]]++,f[p[y[i]]+1]--;//差分
    	for(int i=1;i<w;i++) ans[f[i]+=f[i-1]]+=q[i+1]-q[i];//前缀和累加,然后还原计算答案
    	for(int i=1;i<=n;i++) write(ans[i]),putchar(' ');
    	return 0;
    }
    
  • 相关阅读:
    数据源ObjectDataSource的数据访问类的编写
    ASP.NET网页文本编辑器的使用
    装饰模式
    策略模式
    代理模式
    备份、还原数据库
    简单工厂和工厂模式
    ASP.NET上传多个文件
    数据库访问类的编写
    UVA 11069 A Graph Problem
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/CF1000C.html
Copyright © 2011-2022 走看看