牛客练习赛14
https://www.nowcoder.com/acm/contest/82#question
A. 爆搜
#include <bits/stdc++.h> using namespace std; typedef long long int ll; ll pri[20] = {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53};//16ge ll dfs(ll now,ll res,ll deep,ll maxx){ if(res<pri[deep]) return now; ll k = 1; res/=pri[deep]; ll anss = now*(k+1); while(res>0 && k<=maxx){ anss = max(anss,dfs(now*(k+1),res,deep+1,k)); res/=pri[deep]; k++; } return anss; } int main() { int T; scanf("%d",&T); while(T--){ ll n; scanf("%lld",&n); ll ans = dfs(1,n,0,40); printf("%lld\n",ans); } return 0; }
B预处理以i为左端点,然后跳k次(k=2^0,1,2,3,4,5,6.....)到的下一个点,对于询问l,r就从l开始跳,二进制分解应该跳的次数。复杂度nlogn
#include <bits/stdc++.h> using namespace std; typedef long long int ll; const int maxn = 1e6+9; ll a[maxn]; int rightmost[20][maxn]; int main() { int n,m,k; scanf("%d%d%d",&n,&m,&k); for(int i=1;i<=n;i++){ scanf("%lld",&a[i]); } ll sum = 0; int r = 0; for(int i=1;i<=n;i++){ while(sum+a[r+1]<=k && r+1<=n){ sum+=a[++r]; } rightmost[0][i] = r+1; sum-=a[i]; } rightmost[0][n+1] = n+1; for(int i=1;i<20;i++){ for(int j=1;j<=n+1;j++){ rightmost[i][j] = rightmost[i-1][rightmost[i-1][j]]; } } while(m--){ int ql,qr; scanf("%d%d",&ql,&qr); int ans = 0; int fl = 0; for(int i=19;i>=0;i--){ if(rightmost[i][ql]<=qr){ if(ql==rightmost[i][ql]) fl =1; ans+=(1<<i); ql = rightmost[i][ql]; } } if(fl==1) puts("Chtholly"); else printf("%d\n",ans+1); } return 0; }
C题
求区间内极长连续段的长度是1-10的个数,首先考虑离线做法,把询问按右端点排序,如果我们能在log的时间内处理在i处新加的值x对左端点在前一个x的位置和i之间的右端点处理就行了,首先考虑用前缀和维护区间加法,对[l,r]区间加一等价于l处+1 r+1处-1询问时求前缀和就醒了。
然后是记x之前出现的位置是last 那么我们的任务就是维护右端点在i处 左端点在[last+1,i]的正确值,本来是想k^2维护的,因为可以是左边1个右边1到k个,然后发现这个性质具有单调性,就是如果234不行那么1234肯定不行,所以可以在2k次就把[last+1,i]区间分割,区间分割的依据就是要求这区间恰好是这个极长连续断最大的区间,比如如果当前加入10这个值,那么肯定的我要找到cur=max(last,max(pre[9],pre[11]))的位置,这样,当我们修改[cur+1,i]就是极长连续段只有10所影响的左端点区间,然后我们下一次要分割的区间就是[last+1,cur] 那么cur这个点一定是会包含的,所以我们要更新左极远和右极远的大小,比如如果9在[cur,i]之间的话那么ll++,假设这样结束了那么下一次维护的区间就是cur = max(last,max(pre[8],pre[11]))[cur,上一次的cur] 不断的分割[last+1,cur]直到区间大小为0结束,或者是ll于rr都大于10就没必要维护了
#include <iostream> #include <stdio.h> #include <cstring> #include <vector> #include <map> #include <algorithm> using namespace std; const int maxn = 1e6+9; int a[maxn]; int pre[maxn]; int bitt[11][maxn]; struct node { int l,r,id; bool operator <(node const &a) const { return r<a.r; } }qq[maxn]; char ans[maxn][15]; int lb(int x){return x&(-x);} void add(int *ppp,int pos,int val){ while (pos<maxn) { ppp[pos]+=val; pos+=lb(pos); } } int Q(int *ppp,int pos){ int ret = 0; while (pos) { ret+=ppp[pos]; pos-=lb(pos); } return ret; } void modify(int k,int l,int r,int val){ add(bitt[k], l, val); add(bitt[k], r+1, -val); } int main(int argc, const char * argv[]) { int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); } for(int i=1;i<=m;i++){ scanf("%d%d",&qq[i].l,&qq[i].r); qq[i].id = i; } sort(qq+1,qq+1+m); for(int i=1,j=1;i<=n;i++){ int last = pre[a[i]]; int ll = 0,rr = 0,cur=i; while (last<cur) { int pp = last; if( ll<=10 && a[i]-ll-1>=1) pp = max(pp,pre[a[i]-ll-1]); if( rr<=10 && a[i]+rr+1<=1000000) pp = max(pp,pre[a[i]+rr+1]); if(ll && ll<=10) modify(ll, pp+1, cur, -1); if(rr && rr<=10) modify(rr, pp+1, cur, -1); if(ll+rr+1<=10) { modify(ll+rr+1, pp+1, cur, 1); } while (ll<=10 && a[i]-ll-1>=1 && pre[a[i]-ll-1]>=pp) { ll++; } while (rr<=10 && a[i]+rr+1<=1000000 && pre[a[i]+rr+1]>=pp) { rr++; } if(ll>10 && rr>10) break; cur = pp; } while (j<=m && qq[j].r==i) { for(int k=1;k<=10;k++){ ans[qq[j].id][k] ='0' + Q(bitt[k],qq[j].l)%10; } j++; } pre[a[i]] = i; } for(int i=1;i<=m;i++){ puts(ans[i]+1); } return 0; }
D题水题
E题压位bfs 预处理出距离点i是0,1,2,3.。。。n的点,复杂度不会算
#include <bits/stdc++.h> using namespace std; const int maxn = 1e3+9; bitset<maxn> bb[maxn][maxn]; bitset<maxn> vis; int tot =0; int head[maxn]; struct edge{ int v,nex; }e[100000*2]; vector<int> vv[maxn]; void addedge(int u,int v){ vv[u].push_back(v); } struct node{ int p,deep; }; void bfs(int root){ vis.reset(); queue<node> q; vis.set(root); q.push((node){root,0}); while(!q.empty()){ node now = q.front(); q.pop(); bb[root][now.deep].set(now.p); for(int i=0;i< vv[now.p].size() ;i++){ int v = vv[now.p][i]; if(!vis.test(v)){ vis.set(v); q.push((node){v,now.deep+1}); } } } } int main() { int n,m,q; memset(head,-1,sizeof(head)); scanf("%d%d%d",&n,&m,&q); for(int i=1;i<=m;i++){ int u,v; scanf("%d%d",&u,&v); addedge(u,v); addedge(v,u); } for(int i=1;i<=n;i++){ bfs(i); } for(int i=1;i<=n;i++){ for(int j=1;j<n;j++){ bb[i][j] = bb[i][j-1]|bb[i][j]; } } while(q--){ int t; scanf("%d",&t); bitset<maxn> tmpp; while(t--){ int x,y; scanf("%d%d",&x,&y); tmpp|=bb[x][min(y,n-1)]; } printf("%d\n",tmpp.count()); } return 0; }
F题留坑