9.26模拟赛
由于忘记了kd tree 只写了210分 还写挂了只得了110
T1 loj 6083 数码
题目大意:
给定两个整数l r,对于任意x,满足l<=x<=r 把x的所有约数全部写下来
对于每个写下来的数,只保留最高位的那个数码 求[1,9]中每个数码出现的次数
思路:
对于区间 1 r 用r/i 来统计答案 1<=i<=r
可以发现有些连续的i对答案的贡献是一样的
根据汪神的复杂度分析 统计出每个贡献相同的区间是接近sqrt(n)的
对于每个i 用r/i 即为它的贡献 然后用r/贡献 即为这个贡献的区间的右端点
对于每个区间操作一下即可
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<algorithm> 7 #include<queue> 8 #include<vector> 9 #include<map> 10 #define inf 2139062143 11 #define ll long long 12 #define MAXN 13 using namespace std; 14 inline ll read() 15 { 16 ll x=0,f=1;char ch=getchar(); 17 while(!isdigit(ch)) {if(ch=='-')f=-1;ch=getchar();} 18 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 19 return x*f; 20 } 21 ll ans[11],pw[10]={1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000}; 22 inline void solve(ll l,ll r,ll x) 23 { 24 if(r<10){for(ll i=l;i<=r;i++) ans[i]+=x;return ;} 25 ll mid=*lower_bound(pw,pw+10,l),k=mid/10,i; 26 if(mid<=r) 27 { 28 ans[l/k]+=(ceil((1.0*l/k))*k-l)*x; 29 for(i=ceil((1.0*l/k))*k;i<mid;i+=k) ans[i/k]+=k*x; 30 for(i=mid;i<r;i+=mid) ans[i/mid]+=x*mid; 31 ans[r/mid]+=(r-i+1)*x; 32 return ; 33 } 34 ans[l/k]+=(ceil((1.0*l/k))*k-l)*x; 35 for(i=ceil((1.0*l/k))*k;i<r;i+=k) ans[i/k]+=k*x; 36 ans[r/k]+=(r-i+1)*x; 37 } 38 void work(ll R,ll val) 39 { 40 for(ll i=1,x,y;i<=R;i) 41 { 42 x=R/i,y=R/x; 43 solve(i,y,x*val);i=y+1; 44 } 45 } 46 int main() 47 { 48 //freopen("A.in","r",stdin); 49 //freopen("A.out","w",stdout); 50 ll l=read(),r=read(); 51 work(r,1);work(l-1,-1); 52 for(int i=1;i<=9;i++) printf("%lld\n",ans[i]); 53 }
T2 bzoj 4520 k远点对
题目大意:
平面上n个点 求第k远的欧式距离的平方
思路:
为什么好像kd tree全是裸题
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<algorithm> 7 #include<queue> 8 #include<vector> 9 #include<map> 10 #define inf 2139062143 11 #define ll long long 12 #define MAXN 100100 13 using namespace std; 14 inline ll read() 15 { 16 ll x=0,f=1;char ch=getchar(); 17 while(!isdigit(ch)) {if(ch=='-')f=-1;ch=getchar();} 18 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 19 return x*f; 20 } 21 int n,k,dim,rt; 22 ll tmp; 23 struct node {ll mn[2],mx[2],d[2],l,r;node(){d[0]=d[1]=l=r=0;}}tr[MAXN],g; 24 bool operator < (node a,node b) {return a.d[dim]<b.d[dim];} 25 ll dis(node a,node b) {return (a.d[0]-b.d[0])*(a.d[0]-b.d[0])+(a.d[1]-b.d[1])*(a.d[1]-b.d[1]);} 26 ll Get(node a) 27 { 28 ll res=0; 29 //cout<<g.d[0]<<" "<<g.d[1]<<" "<<a.mn[0]<<" "<<a.mx[0]<<endl; 30 for(int i=0;i<2;i++) 31 res+=max((a.mn[i]-g.d[i])*(a.mn[i]-g.d[i]),(a.mx[i]-g.d[i])*(a.mx[i]-g.d[i])); 32 return res; 33 } 34 priority_queue <ll,vector<ll>,greater<ll> > q; 35 struct kd_tree 36 { 37 void upd(int k) 38 { 39 node l=tr[tr[k].l],r=tr[tr[k].r]; 40 for(int i=0;i<2;i++) 41 { 42 if(tr[k].l) tr[k].mx[i]=max(tr[k].mx[i],l.mx[i]),tr[k].mn[i]=min(tr[k].mn[i],l.mn[i]); 43 if(tr[k].r) tr[k].mx[i]=max(tr[k].mx[i],r.mx[i]),tr[k].mn[i]=min(tr[k].mn[i],r.mn[i]); 44 } 45 } 46 int build(int l,int r,int now) 47 { 48 int mid=(l+r)>>1;dim=now; 49 //cout<<"build: "<<l<<" "<<r<<" "<<mid<<" "<<now<<endl; 50 nth_element(tr+l,tr+mid,tr+r+1); 51 for(int i=0;i<2;i++) tr[mid].mn[i]=tr[mid].mx[i]=tr[mid].d[i]; 52 if(l<mid) tr[mid].l=build(l,mid-1,now^1); 53 //cout<<"build: "<<l<<" "<<r<<" "<<mid<<" "<<now<<" "<<tr[k].l<<" "<<tr[k].r<<endl; 54 if(mid<r) tr[mid].r=build(mid+1,r,now^1); 55 //cout<<"build: "<<l<<" "<<r<<" "<<mid<<" "<<now<<" "<<tr[k].l<<" "<<tr[k].r<<endl; 56 upd(mid);return mid; 57 } 58 void query(int k) 59 { 60 ll dl=0,dr=0,d;d=dis(tr[k],g); 61 if(d>q.top()) q.pop(),q.push(d); 62 if(tr[k].l) dl=Get(tr[tr[k].l]); 63 if(tr[k].r) dr=Get(tr[tr[k].r]); 64 tmp=q.top(); 65 //cout<<k<<" "<<tr[k].l<<" "<<dl<<" "<<tr[k].r<<" "<<dr<<endl; 66 if(dl>dr) 67 { 68 if(dl>tmp) query(tr[k].l);tmp=q.top(); 69 if(dr>tmp) query(tr[k].r); 70 } 71 else 72 { 73 if(dr>tmp) query(tr[k].r);tmp=q.top(); 74 if(dl>tmp) query(tr[k].l); 75 } 76 } 77 }kd; 78 int main() 79 { 80 //freopen("C.in","r",stdin); 81 //freopen("C.out","w",stdout); 82 n=read(),k=read(); 83 for(int i=1;i<=n;i++) tr[i].d[0]=read(),tr[i].d[1]=read(); 84 rt=kd.build(1,n,0);tmp=0; 85 for(int i=1;i<=2*k;i++) q.push(0); 86 for(int i=1;i<=n;i++) 87 { 88 g.d[0]=tr[i].d[0],g.d[1]=tr[i].d[1]; 89 kd.query(rt); 90 } 91 printf("%lld",q.top()); 92 }
T3 loj 6159 最长树链
题目大意:
现在树中的每个点都有一个值,在树中找出最长的链,使得这条链上对应点的值的最大公约数不等于1
请求出这条最长的树链的长度
思路:
对于每个质数 找出能整除这个数的点形成的图
每次求这个图的最长链即可
求出所有的素数 可以先筛出根号1e9以内的素数
分解每个点权的时候 最多还剩一个大质数 加入素数表即可
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<algorithm> 7 #include<queue> 8 #include<vector> 9 #include<map> 10 #define inf 2139062143 11 #define ll long long 12 #define MAXN 200100 13 using namespace std; 14 inline int read() 15 { 16 int x=0,f=1;char ch=getchar(); 17 while(!isdigit(ch)) {if(ch=='-')f=-1;ch=getchar();} 18 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 19 return x*f; 20 } 21 int prm[MAXN],tot,ans,vis[MAXN],ok,val[MAXN],maxn; 22 int n,fst[MAXN],nxt[MAXN],to[MAXN],cnt,mx[MAXN],submx[MAXN]; 23 vector <int> vec[MAXN]; 24 inline void add(int u,int v) {nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v;} 25 inline int isp(int x) 26 { 27 for(int i=2;i*i<=x;i++) if(x%i==0) return 0; 28 return 1; 29 } 30 void mem() 31 { 32 int x=sqrt(1e9); 33 for(int i=2;i<=x;i++) 34 if(isp(i)) prm[++tot]=i; 35 } 36 inline void Div(int x,int id) 37 { 38 int r=sqrt(x),tmp; 39 for(int i=1;prm[i]<=r&&i<=tot;i++) 40 if(x%prm[i]==0) 41 { 42 vec[i].push_back(id); 43 while(x%prm[i]==0) x/=prm[i]; 44 } 45 if(x==1) return ; 46 tmp=*lower_bound(prm+1,prm+tot+1,x); 47 if(tmp) vec[lower_bound(prm+1,prm+tot+1,tmp)-prm].push_back(id); 48 if(!tmp) {prm[++tot]=x;vec[tot].push_back(id);} 49 } 50 void dfs(int x) 51 { 52 mx[x]=submx[x]=0,vis[x]=1; 53 for(int i=fst[x];i;i=nxt[i]) 54 if(!vis[to[i]]&&val[to[i]]%ok==0) 55 { 56 dfs(to[i]); 57 if(mx[to[i]]+1>mx[x]) submx[x]=mx[x],mx[x]=mx[to[i]]+1; 58 else if(mx[to[i]]+1>submx[x]) submx[x]=mx[to[i]]+1; 59 //cout<<ok<<" "<<x<<" "<<to[i]<<" "<<mx[to[i]]<<" "<<submx[x]<<" "<<mx[x]<<endl; 60 } 61 mx[x]=max(mx[x],1); 62 ans=max(ans,submx[x]+mx[x]-(submx[x]!=0)); 63 // cout<<ok<<" "<<x<<" "<<submx[x]<<" "<<mx[x]<<endl; 64 } 65 void Clean(int x) 66 { 67 vis[x]=0; 68 for(int i=fst[x];i;i=nxt[i]) 69 if(vis[x]) Clean(to[i]); 70 // cout<<ok<<" "<<x<<" "<<submx[x]<<" "<<mx[x]<<endl; 71 } 72 int main() 73 { 74 //freopen("C.in","r",stdin); 75 //freopen("C.out","w",stdout); 76 mem();n=read();int a,b; 77 for(int i=1;i<n;i++) {a=read(),b=read();add(a,b);add(b,a);} 78 for(int i=1;i<=n;i++) {val[i]=read();Div(val[i],i);} 79 for(int x=1;x<=tot;x++) 80 { 81 ok=prm[x]; 82 for(int i=0;i<vec[x].size();i++) 83 if(!vis[vec[x][i]]) dfs(vec[x][i]); 84 for(int i=0;i<vec[x].size();i++) 85 if(vis[vec[x][i]]) Clean(vec[x][i]); 86 } 87 printf("%d",ans); 88 }