我是沙波。嘿!
A
好难。
Code
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
string s;
cin>>s;
string t=s;
reverse(t.begin(),t.end());
string x;
for (int i=0; i<t.size(); i++){
if (t[i]=='.') break;
x.push_back(t[i]);
}
reverse(x.begin(),x.end());
cout<<x<<endl;
return 0;
}
]
B
好难。英语太差了。
Code
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int dx[] = {1,0,-1,0};
const int dy[] = {0,-1,0,1};
const int N = 1e2+2;
int n,m,x;
int d[N][N];
void gt(int &a,int b){
if (a<=0){
a+=b;
}
else{
if (a>b){
a=1;
}
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n>>m>>x;
int dir=2,cx=1,cy=1;
for (int i=1; i<=x; i++){
if (d[cx][cy]==1){
d[cx][cy]=0;
dir=(dir-1+4)%4;
cx+=dx[dir],cy+=dy[dir];
gt(cx,n),gt(cy,m);
}
else{
d[cx][cy]=1;
dir=(dir+1)%4;
cx+=dx[dir],cy+=dy[dir];
gt(cx,n),gt(cy,m);
}
}
for (int i=1; i<=n; i++){
for (int j=1; j<=m; j++){
if (d[i][j]==0) cout<<".";
else cout<<"#";
}
cout<<endl;
}
return 0;
}
C
比 A 简单。
点击查看代码
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 2e5+5;
ll n,a[N];
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n;
ll mn=0,cur=0;
for (int i=1; i<=n; i++){
cin>>a[i];
cur+=a[i];
mn=min(mn,cur);
}
cout<<cur-mn<<"\n";
return 0;
}
D
设 \(dp_{a,b,c,d}\) 为两人在 \((a,b),(c,d)\) 的地方最小步数。bfs 即可。
Code
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 66;
const int dx[] = {0,0,-1,1};
const int dy[] = {1,-1,0,0};
struct node {
int a,b,c,d;
};
int n;
string s[N];
int dp[N][N][N][N];
bool Bad(int x,int y){
return x<=0 || y<=0 || x>n || y>n || s[x][y]=='#';
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
memset(dp,-1,sizeof dp);
cin>>n;
int sx1=-1,sy1=-1,sx2=-1,sy2=-1;
for (int i=1; i<=n; i++){
cin>>s[i];
s[i]=" "+s[i];
for (int j=1; j<=n; j++){
if (s[i][j]=='P'){
if (sx1==-1){
sx1=i,sy1=j;
}
else{
sx2=i,sy2=j;
}
}
}
}
queue<node> q;
q.push({sx1,sy1,sx2,sy2});
memset(dp,-1,sizeof dp);
dp[sx1][sy1][sx2][sy2]=0;
while (!q.empty()){
auto u=q.front();
q.pop();
int a=u.a,b=u.b,c=u.c,d=u.d;
for (int i=0; i<4; i++){
int na=a+dx[i],nb=b+dy[i];
int nc=c+dx[i],nd=d+dy[i];
if (Bad(na,nb)){
na=a,nb=b;
}
if (Bad(nc,nd)){
nc=c,nd=d;
}
if (dp[na][nb][nc][nd]==-1){
dp[na][nb][nc][nd]=dp[a][b][c][d]+1;
q.push({na,nb,nc,nd});
}
}
}
int mn=2e9;
for (int a=1; a<=n; a++){
for (int b=1; b<=n; b++){
if (dp[a][b][a][b]!=-1){
mn=min(mn,dp[a][b][a][b]);
}
}
}
if (mn==2e9){
cout<<-1<<endl;
}
else{
cout<<mn<<endl;
}
return 0;
}
E
设 \(dp_i\) 为结尾为 \(i\) 的最大长度。\(dp_{i}=\max_{j=1}^{i-1} dp_j\times [|a_j-a_i|\le d]+1\)。这个可以线段树优化。
没有线段树开 \(4\) 倍空间挂了。
Code
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 5e5+5;
ll n,a[N],d,dp[N],ans;
ll mx[N<<2];
void upd(int k,int l,int r,int x,ll vl){
if (l==r){
mx[k]=max(mx[k],vl);
return;
}
int mid=l+r>>1;
if (x<=mid){
upd(k<<1,l,mid,x,vl);
}
else{
upd(k<<1|1,mid+1,r,x,vl);
}
mx[k]=max(mx[k<<1],mx[k<<1|1]);
}
ll qy(int k,int l,int r,int ql,int qr){
if (l>qr || r<ql){
return 0;
}
if (ql<=l && r<=qr){
return mx[k];
}
int mid=l+r>>1;
ll vl=qy(k<<1,l,mid,ql,qr);
ll vr=qy(k<<1|1,mid+1,r,ql,qr);
return max(vl,vr);
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n>>d;
for (int i=1; i<=n; i++){
cin>>a[i];
}
for (int i=1; i<=n; i++){
dp[i]=qy(1,1,N-1,max(1ll,a[i]-d),min(N-1ll,a[i]+d))+1;
ans=max(ans,dp[i]);
upd(1,1,N-1,a[i],dp[i]);
}
cout<<ans<<endl;
return 0;
}
F
考虑如果给每一个数用一个大质数取模,然后判断时之间判断取模后乘起来想不想等。这样取 \(3\) 次不同的大质数就可以很高概率过。
给 \(ans\) 取模+强度不过挂了。
Code
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e3+3;
const ll mod1 = 998244853;
const ll mod2 = 1e9+9;
const ll mod3 = 1e9+7;
int n;
ll a[N],b[N],c[N];
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n;
map<pair<ll,pair<ll,ll> >,ll> mp;
for (int i=1; i<=n; i++){
a[i]=0;
string s;
cin>>s;
for (auto ch : s){
a[i]=(a[i]*10ll+ch-'0')%mod1;
b[i]=(b[i]*10ll+ch-'0')%mod2;
c[i]=(c[i]*10ll+ch-'0')%mod3;
}
}
for (int i=1; i<=n; i++){
mp[{a[i],{b[i],c[i]}}]++;
}
ll ans=0;
for (int i=1; i<=n; i++){
for (int j=1; j<=n; j++){
ll x=a[i]*a[j]%mod1;
ll y=b[i]*b[j]%mod2;
ll z=c[i]*c[j]%mod3;
ans+=mp[{x,{y,z}}];
}
}
cout<<ans<<endl;
return 0;
}
G
你不会可持久化线段树也可以,比如我。
找到模板题,第 \(k\) 小是什么,然后魔改。二分出 \(x\) 是第几小,然后就可以了。很蠢。
主席树 qy2 return 错了,挂了。
Code
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define int long long
const int N = 2e5+5;
int n,q,m,cnt;
int a[N],b[N],t[N];
int sum[N<<5],ls[N<<5],rs[N<<5],val[N<<5];
int bd(int l,int r){
int k=++cnt;
sum[k]=0;
int mid=l+r>>1;
if (l<r){
ls[k]=bd(l,mid);
rs[k]=bd(mid+1,r);
}
return k;
}
int upd(int pr,int l,int r,int x,ll vl){
int k=++cnt;
ls[k]=ls[pr];
rs[k]=rs[pr];
sum[k]=sum[pr]+1;
val[k]=val[pr]+vl;
int mid=l+r>>1;
if (l<r){
if (x<=mid){
ls[k]=upd(ls[pr],l,mid,x,vl);
}
else{
rs[k]=upd(rs[pr],mid+1,r,x,vl);
}
}
return k;
}
int qy(int u,int v,int l,int r,int k){
if (l>=r){
return l;
}
int x=sum[ls[v]]-sum[ls[u]];
int mid=l+r>>1;
if (x>=k){
return qy(ls[u],ls[v],l,mid,k);
}
else{
return qy(rs[u],rs[v],mid+1,r,k-x);
}
}
int qy2(int u,int v,int l,int r,int k){
if (l>=r){
return val[v]-val[u];
}
int x=sum[ls[v]]-sum[ls[u]];
int vl=val[ls[v]]-val[ls[u]];
int mid=l+r>>1;
if (x>=k){
return qy2(ls[u],ls[v],l,mid,k);
}
else{
return vl+qy2(rs[u],rs[v],mid+1,r,k-x);
}
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n;
for (int i=1; i<=n; i++){
cin>>a[i];
b[i]=a[i];
}
sort(b+1,b+1+n);
m=unique(b+1,b+1+n)-b-1;
t[0]=bd(1,m);
for (int i=1; i<=n; i++){
int pos=lower_bound(b+1,b+1+m,a[i])-b;
t[i]=upd(t[i-1],1,m,pos,a[i]);
}
int lst=0;
cin>>q;
while (q--){
int l,r,k;
cin>>l>>r>>k;
l^=lst,r^=lst,k^=lst;
int lb=0,rb=r-l+2;
while (lb+1<rb){
int mid=lb+rb>>1;
int res=qy(t[l-1],t[r],1,m,mid);
if (b[res]>k){
rb=mid;
}
else{
lb=mid;
}
}
int res=qy2(t[l-1],t[r],1,m,lb);
if (lb==0){
res=0;
}
cout<<res<<"\n";
lst=res;
}
return 0;
}