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
",ans[i]);
53 }
View Code

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 }
View Code

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 }
View Code
原文地址:https://www.cnblogs.com/yyc-jack-0920/p/9706455.html