Codeforces 515
515 C
题意
定义一个函数 \(F(x)\) ,举例: \(F(123450)=1!*2!*3!*4!*5!*0!\) 。
现在给你一个数 \(a\) ,最多 \(15\) 位,求最大的数 \(x\) ,使得:
- \(x\) 中不包含 \(0\) 和 \(1\) 数码;
- \(F(x)=F(a)\) 。
Examples
input
4
1234
output
33222
input
3
555
output
555
解
首先,要尽量把大数的阶乘分解成若干个小数的阶乘。
其次,各个数码应该从大到小排列,这样才最优。
再次,
Code
#include<bits/stdc++.h>
#define maxn 103
using namespace std;
template<typename tp>
void read(tp& x){
x=0;
char c=getchar();
bool sgn=0;
while((c<'0'||c>'9')&&c!='-')c=getchar();
if(c=='-')sgn=1,c=getchar();
while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+c-'0',c=getchar();
if(sgn)x=-x;
}
template<typename tp>
void write(tp x){
if(x<0)putchar('-'),write(-x);
else{
if(x>=10)write(x/10);
putchar(x%10+'0');
}
}
int a[11],b[17],n;
char c[17];
int main(){
read(n);
scanf("%s",c);
for(int i=1;i<=n;i++){
b[i]=c[i-1]-'0';
a[b[i]]++;
}
for(int i=9;i>=2;i--){
if(i==9)a[7]+=a[9],a[3]+=a[9]*2,a[2]+=a[9],a[9]=0;
if(i==8)a[7]+=a[8],a[2]+=a[8]*3,a[8]=0;
if(i==6)a[5]+=a[6],a[3]+=a[6],a[6]=0;
if(i==4)a[3]+=a[4],a[2]+=a[4]*2,a[4]=0;
}
for(int i=1;i<=a[7];i++)putchar('7');
for(int i=1;i<=a[5];i++)putchar('5');
for(int i=1;i<=a[3];i++)putchar('3');
for(int i=1;i<=a[2];i++)putchar('2');
return 0;
}
515 E
题意
有 \(n\) 棵树围成一个环,现在有 \(m\) 组询问,每组包含两个数 \(a_i,b_i\) ,表示 \(a_i-b_i\) 的所有树被占领,你不能经过,现在告诉你每两棵树之间的距离 \(d_i\) (表示 \(i\) 到 \(i+1\) 的距离)、树的高度 \(h_i\) ,你能获得的收益为 \(2*(h_i+h_j)+\sum_{k为i-j的路径上所有的树}d_k\) ,现在对于每个询问,请你输出最大的收益。 \((n,m\le 10^5)\)
Examples
input
5 3
2 2 2 2 2
3 5 2 1 4
1 3
2 2
4 5
output
12
16
18
input
3 3
5 1 4
5 1 4
3 3
2 2
1 1
output
17
22
11
解
首先,处理环的一般方式:将数组扩大一倍
然后,问题变为求一段区间的最大子段和,可以用线段树维护。
方法:每个节点维护六个值。
设 \(lmx\) 表示区间中最大 \(d_i\) 子段和(有个端点在区间左端点,不包括端点的 \(h_i\)), \(rmx\) 表示区间中最大 \(d_i\) 子段和(有个端点在区间右端点,不包括端点的 \(h_i\)),\(mx\) 表示区间中最大 \(d_i\) 子段和(不包括端点的 \(h_i\)); \(lr,rr,r\) 与上述变量意义相同,但包括端点的 \(h_i\)。
\(\text{long long}\)
Code
#include<bits/stdc++.h>
#define maxn 200003
using namespace std;
struct node{
long long lmx,rmx,mx,lr,rr,r;
node():lmx(0),rmx(0),mx(0),lr(0),rr(0),r(0){}
}t[maxn<<2];
int n,d[maxn],h[maxn],m;
void pushup(node& t1,const node& t2,const node& t3,int mid){
t1.lmx=max(t2.lmx,t3.lmx+t2.mx+d[mid]);
t1.rmx=max(t3.rmx,t2.rmx+t3.mx+d[mid]);
t1.mx=max(max(t2.mx,t3.mx),t2.rmx+t3.lmx+d[mid]);
t1.lr=max(t2.lr,t3.lr+t2.mx+d[mid]);
t1.rr=max(t3.rr,t2.rr+t3.mx+d[mid]);
t1.r=max(max(t2.r,t3.r),t2.rr+t3.lr+d[mid]);
}
void build(int p,int l,int r){
if(l==r){
t[p].lmx=t[p].rmx=t[p].mx=0;
t[p].lr=t[p].rr=t[p].r=2ll*h[l];
return;
}
int mid=(l+r)>>1;
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
pushup(t[p],t[p<<1],t[p<<1|1],mid);
}
node query(int p,int l,int r,int seg_l,int seg_r){
if(seg_l<=l&&r<=seg_r){
return t[p];
}
int mid=(l+r)>>1;
node tmp1,tmp2,ret;
if(seg_l<=mid&&seg_r>mid){
tmp1=query(p<<1,l,mid,seg_l,seg_r);
tmp2=query(p<<1|1,mid+1,r,seg_l,seg_r);
pushup(ret,tmp1,tmp2,mid);
}
else if(seg_l<=mid)ret=query(p<<1,l,mid,seg_l,seg_r);
else if(seg_r>mid)ret=query(p<<1|1,mid+1,r,seg_l,seg_r);
return ret;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%d",d+i),d[i+n]=d[i];
for(int i=1;i<=n;i++)scanf("%d",h+i),h[i+n]=h[i];
build(1,1,n+n);
while(m--){
int a,b;
scanf("%d%d",&a,&b);
if(a<=b){
a+=n-1;
b++;
}
else{
a--;
b++;
}
node tmp=query(1,1,n+n,b,a);
cout<<tmp.r<<endl;
}
return 0;
}