CSP-S模拟68 题解
Posted leom10
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CSP-S模拟68 题解相关的知识,希望对你有一定的参考价值。
T1:
不难想到贪心,但是怎么贪,他有两个限制条件,所以不是很好搞,所以用一个类似与wqs二分的思路我可能在口胡,因为你肯定要把最小的给删掉,所以你限定一个x或y,然后在选出另一个限制,所以要同时维护删$k$个$x$最小和$y$最小,一个排序预处理,一个用堆维护即可。注意边界问题,思考实际意义。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define int long long 4 const int N=1e5+10; 5 int a[N]; 6 priority_queue<int> qx,qy; 7 struct node{ 8 int x,y; 9 bool friend operator < (node a,node b){ 10 return a.x==b.x?(a.y<b.y):(a.x<b.x); 11 } 12 }p[N]; 13 signed main(){ 14 int T; 15 scanf("%lld",&T); 16 while(T--){ 17 int n,m; 18 scanf("%lld%lld",&n,&m); 19 priority_queue<int,vector<int>,greater<int> >q; 20 for(int i=1;i<=n;++i){ 21 scanf("%lld%lld",&p[i].x,&p[i].y); 22 } 23 sort(p+1,p+n+1); 24 for(int i=m+1;i<=n;++i) q.push(p[i].y); 25 int ans=p[m+1].x*q.top(); 26 for(int i=m;i>=0;--i){ 27 q.pop();q.push(p[i].y); 28 ans=max(ans,p[i].x*q.top()); 29 } 30 printf("%lld ",ans); 31 } 32 }
T2:
考试时啥都没想到,连那个最小联通块都没分析出来是什么。通过手玩可以发现他所说的最小联通块就是所有点的LCA到每个节点的链,然后对于每一个询问值,只要查他的前趋后继即可,思路类似于平衡树那道题,宠物收养所,然后树上每条链其实就是树上的一段区间,用主席树维护即可,具体方法为查询问的值在区间的排名$rk$(准确来说是小于等于它的数的个数),然后前趋排名为$rk$,后继为$rk+1$,在查区间第k大即可,注意特判没有前趋或后继的情况。
特别注意在线不要只把值赋给LCA,$p[1]$也要改。
调了一下午 kuku
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=1e5+10; 4 struct Chairman_Tree{ 5 int l,r,size; 6 }tr[N*40]; 7 int first[N],nex[N<<1],to[N<<1],tot,fr[N<<1]; 8 void add(int a,int b){ 9 to[++tot]=b,nex[tot]=first[a],first[a]=tot,fr[tot]=a; 10 } 11 int fa[N][22],d[N],root[N*40],p[N*3],a[N]; 12 void bfs(){ 13 queue<int> q; 14 q.push(1); 15 d[1]=1; 16 while(q.size()){ 17 int x=q.front();q.pop(); 18 for(int i=first[x];i;i=nex[i]){ 19 int y=to[i]; 20 if(d[y]) continue; 21 d[y]=d[x]+1; 22 fa[y][0]=x; 23 for(int j=1;j<=19;++j) fa[y][j]=fa[fa[y][j-1]][j-1]; 24 q.push(y); 25 } 26 } 27 } 28 int LCA(int x,int y){ 29 if(d[x]>d[y]) swap(x,y); 30 for(int i=19;i>=0;--i) if(d[fa[y][i]]>=d[x]) y=fa[y][i]; 31 if(x==y) return x; 32 for(int i=19;i>=0;--i) if(fa[y][i]!=fa[x][i]) y=fa[y][i],x=fa[x][i]; 33 return fa[x][0]; 34 } 35 int cnt; 36 void insert(int &x,int v,int l,int r,int pos){ 37 x=++cnt; 38 tr[x]=tr[v]; 39 tr[x].size++; 40 if(l==r) return ; 41 int mid=(l+r)>>1; 42 if(pos<=mid) insert(tr[x].l,tr[v].l,l,mid,pos); 43 else insert(tr[x].r,tr[v].r,mid+1,r,pos); 44 } 45 int maxn=0; 46 void dfs(int x){//cout<<"x=="<<x<<endl; 47 // cout<<x<<" "<<fa[x][0]<<" "<<a[x]<<endl; 48 insert(root[x],root[fa[x][0]],1,maxn,a[x]); 49 for(int i=first[x];i;i=nex[i]){ 50 int y=to[i]; 51 if(y==fa[x][0]) continue; 52 dfs(y); 53 } 54 } 55 int query(int u,int v,int l,int r,int val){ 56 if(r<=val) return tr[v].size-tr[u].size; 57 int mid=(l+r)>>1; 58 int als=tr[tr[v].l].size-tr[tr[u].l].size; 59 if(val<=mid) return query(tr[u].l,tr[v].l,l,mid,val); 60 else return als+query(tr[u].r,tr[v].r,mid+1,r,val); 61 } 62 int kth(int u,int v,int l,int r,int rk){ 63 if(l==r) return l; 64 int mid=(l+r)>>1; 65 int als=tr[tr[v].l].size-tr[tr[u].l].size; 66 if(rk<=als) return kth(tr[u].l,tr[v].l,l,mid,rk); 67 else return kth(tr[u].r,tr[v].r,mid+1,r,rk-als); 68 } 69 70 int find(int x,int fa,int val){ 71 int tmp=query(root[fa],root[x],1,maxn,val); 72 int fr=tmp,aft=tmp+1; 73 // cout<<"tmp=="<<tmp<<endl; 74 int frv=0x7fffffff,aftv=0x7fffffff; 75 // if(aft>d[x]-d[fa]) cout<<"HHH"<<endl; 76 int res=0x7fffffff; 77 if(fr>0) frv=kth(root[fa],root[x],1,maxn,fr),res=min(res,abs(frv-val)); 78 if(aft<=tr[root[x]].size-tr[root[fa]].size) aftv=kth(root[fa],root[x],1,maxn,aft),res=min(res,abs(aftv-val)); 79 // cout<<"x=="<<x<<" fa=="<<fa<<" val=="<<val<<endl; 80 // cout<<"fr=="<<fr<<" aft=="<<aft<<endl; 81 // cout<<"frv=="<<frv<<" aftv=="<<aftv<<endl; 82 return res; 83 } 84 85 int main(){ 86 int n,q,type; 87 scanf("%d%d%d",&n,&q,&type); 88 for(int i=1;i<=n;++i) {scanf("%d",&a[i]);maxn=max(maxn,a[i]);} 89 for(int i=1;i<n;++i){ 90 int x,y; 91 scanf("%d%d",&x,&y); 92 add(x,y); 93 add(y,x); 94 } 95 bfs(); 96 // for(int i=1;i<=tot;++i) cout<<fr[i]<<" "<<to[i]<<endl; 97 dfs(1); 98 int lastans=0; 99 for(int i=1;i<=q;++i){ 100 int rvalue,k; 101 scanf("%d%d",&rvalue,&k); 102 scanf("%d",&p[1]); 103 int lca=p[1]=(p[1]-1+lastans*type)%n+1; 104 for(int j=2;j<=k;++j){ 105 scanf("%d",&p[j]); 106 p[j]=(p[j]-1+lastans*type)%n+1; 107 lca=LCA(lca,p[j]); 108 } 109 // cout<<"Lca=="<<lca<<endl; 110 int ans=0x7fffffff; 111 for(int j=1;j<=k;++j) ans=min(ans,find(p[j],fa[lca][0],rvalue)); 112 lastans=ans; 113 printf("%d ",ans); 114 } 115 } 116 /* 117 3 1 0 118 18 99 59 119 1 2 120 2 3 121 15 3 2 2 3 122 */
T3:不会,鸽了
以上是关于CSP-S模拟68 题解的主要内容,如果未能解决你的问题,请参考以下文章