/*
A 题
题意:中文
解题:此题果断二分,时间复杂度为 n*lgn ,注意最后的结果是 min ,理解其意
*/
#include<iostream>
#include<cstdio>
#include<string>
#include<algorithm>
#define manx 100009
using namespace std;
long long a[manx];
int main(){
int n;
while(scanf("%d",&n)!=EOF){
long long min=2000000009,max=0,sum=0;
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
if(min>a[i]) min=a[i];
if(max<a[i]) max=a[i];
}
long long mid=(max+min)>>1,flag=0;
while(max>min){
sum=0; flag=0;
mid=(max+min)>>1;
for(int i=1;i<=n;i++){
if(sum+mid<a[i]) { flag=1; break; }
sum=sum+mid-a[i];
}
if(flag){
min=mid+1; continue;
}
max=mid;
}
printf("%lld\n",min);
}
}
/*
D 题
这道题想了我不知道多久了,一下午 + 一晚上 + 一上午,尼玛啊,总算是找到规律了。。
方法总结:找每个点的必败点,也就是找最大的菱形,然后计算对点的步数。。
*/
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int main(){
int n,m ;
while(cin>>n>>m){
if(n==m){
if(n%3==2)cout<<"Alice"<<endl;
else cout<<"Bob"<<endl;
continue;
}
int k=min(n,m);
if(k%3==0) cout<<"Bob"<<endl;
else cout<<"Alice"<<endl;
}
}
/*
E题, 题意:中文
此题就是一道裸的KMP模板题
*/
#include<iostream>
#include<cstdio>
#include<string>
#define manx 100009
using namespace std;
char a[manx*2],b[manx];
int n,m,next[manx];
void get_next(){ 求next的值
int i=1,j=0;
next[1]=0; 固定的值初始化 next[2]=1;
while(i<m){
if(j==0||b[i]==b[i]){
++i,++j;
next[i]=j; 这里是递推关系
}
else j=next[j]; 注意了 这里是重点 ,采用了记忆化
}
}
int kmp(){
int i=1,j=1;
while(i<=n&&j<=m){ /// 匹配限制条件
if(j==0||a[i]==b[j]){ /// 匹配成立条件
++i;++j;
}
else j=next[j]; /// 转换,,思想真的要严老师讲了才知道
}
if(j>m) return i-m;
return 0;
}
int main(){
while(cin>>a+1>>b+1){
n=strlen(a+1);
m=strlen(b+1);
if(!strcmp(a+1,b+1)){ printf("0\n"); continue;}
int k=n;
for(int i=n+1,j=1;i<=n+n && j<=n;i++,j++)
a[i]=a[j];
n=n+n;
get_next();
int flag=kmp();
if(!flag) printf("-1\n");
else printf("%d\n",k-flag+1);
}
}
/*
C题,裸的线段树,只是要维护几个节点的值。。。
*/
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define manx 100100
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
long long root[manx*4],x[manx],sum[manx*4],ans[manx*4],flag,val;
void make(int l,int r,int rt){
if(l==r) { root[rt]=x[l]; sum[rt]=x[l]; ans[rt]=x[l]; return ; }
int mid=(l+r)>>1;
make(lson);
make(rson);
root[rt]=root[rt<<1] & root[(rt<<1)|1];
sum[rt]=sum[rt<<1] ^ sum[(rt<<1)|1];
ans[rt]=ans[rt<<1] | ans[(rt<<1)|1];
}
void query(char s,int ll,int rr,int l,int r,int rt){
if(ll<=l && rr>=r){
if(!flag){
if(s=='a') val=root[rt];
if(s=='x') val=sum[rt];
if(s=='o') val=ans[rt];
flag=1;
}
else{
if(s=='a') val=val & root[rt];
if(s=='x') val=val ^ sum[rt];
if(s=='o') val=val | ans[rt];
}
return ;
}
int mid = (l+r)>>1;
if(rr<=mid) query(s,ll,rr,lson);
else if(ll>mid) query(s,ll,rr,rson);
else {
query(s,ll,rr,lson);
query(s,ll,rr,rson);
}
}
int main(){
int n,m;
while(cin>>n>>m){
for(int i=1;i<=n;i++)
scanf("%lld",&x[i]);
make(1,n,1);
char s[4];
int l,r;
for(int i=0;i<m;i++){
val=0; flag=0;
scanf("%s %d %d",s,&l,&r);
query(s[0],l,r,1,n,1);
printf("%lld\n",val);
}
}
}
/*
F 题,建树
解题:先把每个元素看成一个单个集合,然后找出一个大集合作为主集合,
每次找出一个大集合,然后进行合并 。。。
*/
#include<iostream>
#include<algorithm>
using namespace std;
#define manx 20
int x[manx],s[manx],pre[manx];
int n,ans;
int judge(){ ///判断树是否建成
for(int i=1;i<=n;i++)
if(x[i]) return 1;
return 0;
}
int query(){ /// 找出大集合
int max=0,ans;
for(int i=1;i<=n;i++){
if(s[i]) continue;
if(max<x[i]) max=x[i],ans=i;
}
return ans;
}
void fan(int pos){ /// 进行合并
for(int i=1;i<=n;i++){
if(s[i] && x[i]){
x[i]--;
x[pos]--;
s[pos]=1;
pre[pos]=i;
return ;
}
}
}
int main(){
while(cin>>n){
int max=0;
for(int i=1;i<=n;i++){
s[i]=0; pre[i]=i;
cin>>x[i];
if(x[i]>max) max=x[i],ans=i;
}
s[ans]=1;
while(judge()){
int pos=query();
fan(pos);
}
for(int i=1;i<=n;i++){
if(pre[i]==i) continue;
cout<<i<<" "<<pre[i]<<endl;
}
}
}