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题留坑