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 ",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]); }