CF上的3道小题(2)

CF上的3道小题(2)

T1:CF630K Indivisibility

题意:给出一个数n,求1到n的数中不能被2到9中任意一个数整除的数。

分析:容斥一下,没了。

代码:

#include <cstdio>
#include <string.h>
#include <algorithm>
#include <cstdlib>
using namespace std;
typedef long long ll;
ll n;
ll solve() {
	return n-n/2-n/3-n/5-n/7+n/6+n/10+n/14+n/15+n/21+n/35-n/30-n/42-n/70-n/105+n/210;
}
int main() {
	freopen("ah.in","r",stdin);
	freopen("ah.out","w",stdout);
	scanf("%lld",&n);
	printf("%lld\n",solve());
}

 T2:CF690C3. Brain Network (hard)

题意:每次加一个点,求这棵树的直径。

分析:直径的两个端点最多替换下去一个,于是分别求一下新点到两个端点的距离更新答案即可。

距离倍增一下。

代码:

#include <cstdio>
#include <string.h>
#include <algorithm>
#include <cstdlib>
using namespace std;
inline char nc() {
    static char buf[100000],*p1,*p2;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
int rd() {
    int x=0; char c=nc();
    while(c<'0'||c>'9') c=nc();
    while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-'0',c=nc();
    return x;
}
#define N 200050
int n,ans,f[22][N],g[N],h[N],p1,p2,dep[N];
int lca(int x,int y) {
	int i;
	if(dep[x]<dep[y]) swap(x,y);
	for(i=21;i>=0;i--) {
		if(dep[f[i][x]]>=dep[y]) x=f[i][x];
	}
	if(x==y) return x;
	for(i=21;i>=0;i--) {
		if(f[i][x]!=f[i][y]) {
			x=f[i][x]; y=f[i][y];
		}
	}
	return f[0][x];
}
int main() {
	// freopen("name.in","r",stdin);
	// freopen("name.out","w",stdout);
	n=rd();
	int i,x,j;
	dep[1]=1;
	p1=p2=1;
	int flg=0;
	for(i=2;i<=n;i++) {
		x=rd();
		f[0][i]=x;
		dep[i]=dep[x]+1;
		for(j=1;j<=21;j++) {
			f[j][i]=f[j-1][f[j-1][i]];
		}
		int l=lca(p1,i);
		if(dep[i]+dep[p1]-dep[l]-dep[l]>ans) {
			ans=dep[i]+dep[p1]-dep[l]-dep[l]; p2=i;
		}
		l=lca(p2,i);
		if(dep[i]+dep[p2]-dep[l]-dep[l]>ans) {
			ans=dep[i]+dep[p2]-dep[l]-dep[l]; p1=i;
		}
		if(!flg) flg=printf("%d",ans);
		else printf(" %d",ans);
	}
}

 

 T3:CF685D Kay and Eternity

题意:网格平面上有n个格子被涂黑,第i个黑色格子的坐标为(xi,yi)。对于在区间[1,n]中的每一个整数x,求恰好包含x个黑色格子的k*k的矩形个数。数据保证所有n个格子不相同。

分析:借鉴了一下题解的代码。

每个点对应一个k*k的正方形(不妨设其为右下角)。把xi到xi+K-1这段点离散。

然后对于每个y拆成y-K+1和y两个点,一个表示1一个表示-1。扫描线从下往上扫。

每次求出sum[i]表示这个点以下覆盖了多少黑点,lst[i]表示上一次扫的y。

对每个sum[i]的答案+=y-lst[i]。

实际上离散2n个点就可以,空间还小。

我这里nk的空间不能直接开数组。

代码:

#include <cstdio>
#include <string.h>
#include <algorithm>
#include <cstdlib>
#include <vector>
using namespace std;
#define N 100001
typedef long long ll;
struct Point {
	int x,y;
	bool operator < (const Point &p) const {
		return x<p.x;
	}
}a[N];
struct Q {
	int l,r,y,type,rl,rr;
	bool operator < (const Q &x) const {
		return y<x.y;
	}
}q[N<<1];
vector<int>tt;
int K,n;
ll ans[N];
int main() {
	scanf("%d%d",&n,&K);
	int i,cnt=0,j,tot=0;
	for(i=1;i<=n;i++) scanf("%d%d",&a[i].x,&a[i].y);
	sort(a+1,a+n+1);
	for(i=1;i<=n;i++) {
		int st=(!tt.empty())?max(tt.back()+1,a[i].x-K+1):a[i].x-K+1;
		for(j=st;j<=a[i].x;j++) tt.push_back(j);
	}
	for(i=1;i<=n;i++) {
		q[++tot].rl=a[i].x-K+1; q[tot].rr=a[i].x; q[tot].y=a[i].y-K+1; q[tot].type=1;
		q[++tot].rl=a[i].x-K+1; q[tot].rr=a[i].x; q[tot].y=a[i].y+1; q[tot].type=-1;
	}
	for(i=1;i<=tot;i++) {
		q[i].l=lower_bound(tt.begin(),tt.end(),q[i].rl)-tt.begin();
		q[i].r=upper_bound(tt.begin(),tt.end(),q[i].rr)-tt.begin();
	}
	cnt=tt.size();
	tt.clear();
	tt.shrink_to_fit();
	sort(q+1,q+tot+1);
	vector<int>sum(cnt,0);
	vector<int>lst(cnt,0x3f3f3f3f);
	for(i=1;i<=tot;i++) {
		int l=q[i].l,r=q[i].r;
		for(j=l;j<r;j++) {
			if(lst[j]!=0x3f3f3f3f) {
				ans[sum[j]]+=q[i].y-lst[j];
			}
			sum[j]+=q[i].type;
			lst[j]=q[i].y;
		}
	}
	for(i=1;i<=n;i++) printf("%lld ",ans[i]);
}

 

 

posted @ 2018-06-08 15:09  fcwww  阅读(256)  评论(0编辑  收藏  举报