比较奇怪的比赛..?
T1
简单分析后可知
应求出每个位置起,异或和单调不下降的最右侧端点
Ri
R
i
答案则是
∑ri=lmin(r,Ri)−i+1
∑
i
=
l
r
m
i
n
(
r
,
R
i
)
−
i
+
1
求出
Ri
R
i
后,用主席树维护答案是比较明显的(R_i的和以及个数)
但是暴力求
Ri
R
i
的复杂度是
n2
n
2
的
单独考虑
Ai=0
A
i
=
0
的情况
把这些数去掉后,
Ri
R
i
可以稍作修改求出
剩下部分暴力求
Ri
R
i
的复杂度是
nlogAi
n
l
o
g
A
i
证明…先略。
Code
#include<bits/stdc++.h>
using namespace std;
#define Death Komachi
#define Uni :All right
#define REP(i,a,b) for(int i=(a),i##_end_=(b);i<i##_end_;++i)
#define DREP(i,a,b) for(int i=(a),i##_end_=(b);i>i##_end_;--i)
#define LREP(i,a) for(int i=Head[a];i;i=Next[i])
#define M 100004
#define LL long long
void Rd(int &x){
static char c;x=0;
while((c=getchar())<48);
do x=(x<<3)+(x<<1)+(c^48);
while((c=getchar())>47);
}
static const int N=M*20;
int n,m,A[M],Nxt[M],R[M];
int Rt[M],Lp[N],Rp[N],Cnt[N],tot;
LL Sum[N];
#define lson l,mid,Lp[p]
#define rson mid+1,r,Rp[p]
void Insert(int l,int r,int &p,int a,int old){
p=++tot;
Sum[p]=Sum[old]+a;
Cnt[p]=Cnt[old]+1;
if(l!=r){
int mid=l+r>>1;
if(a<=mid)Rp[p]=Rp[old],Insert(lson,a,Lp[old]);
else Lp[p]=Lp[old],Insert(rson,a,Rp[old]);
}
}
void Query(int l,int r,int p,int a,int &c,LL &s){
if(!p || a<l)return;
if(r<=a){
s+=Sum[p],c+=Cnt[p];
return;
}
int mid=l+r>>1;
Query(lson,a,c,s);
Query(rson,a,c,s);
}
int main(){
Rd(n);
REP(i,1,n+1)Rd(A[i]);
Nxt[n+1]=R[n+1]=n+1;
DREP(i,n,0)
Nxt[i]=A[i+1]?i+1:Nxt[i+1];
DREP(i,n,0){
if(!A[i])R[i]=R[i+1];
else{
int s=A[i],&j=R[i];
for(j=i;j!=n+1;j=Nxt[j])
if(s<=(s^A[Nxt[j]]))s^=A[Nxt[j]];
else break;
j=Nxt[j]-1;
}
}
REP(i,1,n+1)
Insert(1,n,Rt[i],min(n,R[i]),Rt[i-1]);
LL Ans=0;
Rd(m);
while(m--){
int l,r,c=0;
LL s=0;
Rd(l),Rd(r);
l=(l+Ans)%n+1,r=(r+Ans)%n+1;
if(l>r)swap(l,r);
Query(1,n,Rt[l-1],r,c,s),c=-c,s=-s;
Query(1,n,Rt[r],r,c,s);
Ans=s+(LL)(r-l+1-c)*r-((LL)(l+r-2)*(r-l+1)>>1);
printf("%lld\n",Ans);
}
return 0;
}
T2
对于较高的位置,
填完之后可以把其剩下砖块放到低于其的所有位置。
但不能转移到另一个较高的位置。
那么先贪心填较高的位置是没有问题的。
考虑分治,现在求到区间
[l,r]
[
l
,
r
]
,底线为
h
h
求出当前区间最低位置,其高度为
t
t
当前需要填的砖块数为
分别求
(l,c−1,t)
(
l
,
c
−
1
,
t
)
和
(c+1,r,t)
(
c
+
1
,
r
,
t
)
所剩下来的砖块数量放到当前位置。
然后除k向上取整求出需要多放的次数即可。
返回剩下的砖块。
单调栈优化一下能做到
O(n)
O
(
n
)
。
Code
#include<bits/stdc++.h>
using namespace std;
#define Death Komachi
#define Uni :All right
#define REP(i,a,b) for(int i=(a),i##_end_=(b);i<i##_end_;++i)
#define LL long long
static const int M=1000004,K=20;
void Rd(int &x){
static char c;x=0;
while((c=getchar())<48);
do x=(x<<3)+(x<<1)+(c^48);
while((c=getchar())>47);
}
int n,m,H[M],Log2[M],RMQ[M][K];
LL Ans,s;
int Cmp(int a,int b){return H[a]<H[b]?a:b;}
LL Solve(int l,int r,int h){
if(l>r)return 0;
int k=Log2[r-l+1];
int c=Cmp(RMQ[l][k],RMQ[r-(1<<k)+1][k]),t=H[c];
LL Res=Solve(l,c-1,t)+Solve(c+1,r,t);
LL Sum=(LL)(t-h)*(r-l+1);
LL Tmp=max(0ll,(Sum-Res+m-1)/m);
Ans+=Tmp;
return Res+Tmp*m-Sum;
}
int main(){
Rd(n),Rd(m);
REP(i,2,n+1)Log2[i]=Log2[i>>1]+1;
REP(i,1,n+1)Rd(H[i]),RMQ[i][0]=i;
int j;
REP(k,1,K)REP(i,1,n+1)if((j=i+(1<<k-1))<=n)
RMQ[i][k]=Cmp(RMQ[i][k-1],RMQ[j][k-1]);
else break;
Solve(1,n,0);
printf("%lld\n",Ans);
return 0;
}
T3
补完中..