T1
考试时用了个神学做法水了85分,um其实和标答也就一个vecto/set的区别,数据可能是脚造的8
先预处理翻转前的固定点做前缀和,然后枚举对称轴,由内向外进行更新
然后就是,set的优先级和priority_queue相反的,然后重载运算符的时候不用反着来
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <set>
#define maxn 1000010
using namespace std;
int n,ans,a[maxn],sum[maxn];
int read()
{
int xx=0,kk=1;char ch=' ';
while(!isdigit(ch)){ch=getchar();if(ch=='-')kk=-1;}
while(isdigit(ch)){xx=xx*10+ch-'0';ch=getchar();}
return kk*xx;
}
struct node
{
int i,ai;
node(int i,int ai):i(i),ai(ai){};
bool operator <(const node&a)const
{
return max(i,ai)<max(a.i,a.ai);
}
};
multiset<node> v[maxn<<1];
int main()
{
freopen("rotate.in","r",stdin);
freopen("rotate.out","w",stdout);
n=read();
for(int i=1;i<=n;++i)
a[i]=read(),v[a[i]+i].insert((node(i,a[i])));
for(int i=1;i<=n;++i)
sum[i]=sum[i-1]+(a[i]==i);
for(int i=1;i<=2*n;++i)
{
int tmp=0;
while(v[i].size())
{
tmp++;
node now=*v[i].begin();
v[i].erase(v[i].begin());
int maxi=max(now.i,now.ai);
int mini=min(now.i,now.ai);
ans=max(ans,sum[mini-1]+tmp+sum[n]-sum[maxi]);
}
}
printf("%d",ans);
return 0;
}
/*
12
10 9 8 4 6 5 7 3 2 1 12 11
*/
T2
比较有意思的最短路问题,考试的时候太sb了,没有考虑到周围都没有墙的情况,直接bfs居然还得了25...
考虑四周没有墙的情况其实就是往这个点上下左右的格子连长1的边,然后上下左右的墙连一条长dis+1的边,其中dis就等于这个格子到其上下左右的墙的最短距离
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <queue>
#define inf 1e9
#define maxn 520
#define maxm 250100
using namespace std;
char ch[maxn];
int n,m,num,s,t;
bool vis[maxm],obs[maxm];
int l[maxm],r[maxm],u[maxm],d[maxm],dis[maxm],fir[maxm];
struct qwq
{
int nxt,to,val;
}e[maxm<<3];
struct qvq
{
int u,d;
bool operator <(const qvq&a)const
{
return d>a.d;
}
};
priority_queue<qvq> q;
int getnum(int i,int j)
{
return (i-1)*m+j;
}
void addedge(int u,int v,int w)
{
e[++num].to=v;
e[num].val=w;
e[num].nxt=fir[u];
fir[u]=num;
}
void dijkstra(int s)
{
for(int i=1;i<=n*m;++i) dis[i]=inf;
dis[s]=0,q.push((qvq){s,dis[s]});
while(!q.empty())
{
qvq sx=q.top();q.pop();
int u=sx.u,d=sx.d;
if(dis[u]!=d) continue;
for(int i=fir[u];i;i=e[i].nxt)
{
int v=e[i].to;
if(dis[u]+e[i].val<dis[v])
{
dis[v]=dis[u]+e[i].val;
q.push((qvq){v,dis[v]});
}
}
}
}
int main()
{
freopen("cell.in","r",stdin);
freopen("cell.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)
{
scanf("%s",ch+1);
for(int j=1;j<=m;++j)
{
if(ch[j]=='#') obs[getnum(i,j)]=true;
if(ch[j]=='C') s=getnum(i,j);
if(ch[j]=='F') t=getnum(i,j);
}
}
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
{
l[getnum(i,j)]=r[getnum(i,j)]=j;
u[getnum(i,j)]=d[getnum(i,j)]=i;
}
for(int i=2;i<=n;++i)
for(int j=1;j<=m;++j)
if(!obs[getnum(i-1,j)]) u[getnum(i,j)]=u[getnum(i-1,j)];
for(int i=n-1;i>=1;--i)
for(int j=1;j<=m;++j)
if(!obs[getnum(i+1,j)]) d[getnum(i,j)]=d[getnum(i+1,j)];
for(int i=1;i<=n;++i)
for(int j=2;j<=m;++j)
if(!obs[getnum(i,j-1)]) l[getnum(i,j)]=l[getnum(i,j-1)];
for(int i=1;i<=n;++i)
for(int j=m-1;j>=1;--j)
if(!obs[getnum(i,j+1)]) r[getnum(i,j)]=r[getnum(i,j+1)];;
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
{
if(obs[getnum(i,j)]) continue;
if(i>1&&!obs[getnum(i-1,j)])addedge(getnum(i,j),getnum(i-1,j),1);
if(i<n&&!obs[getnum(i+1,j)])addedge(getnum(i,j),getnum(i+1,j),1);
if(j>1&&!obs[getnum(i,j-1)])addedge(getnum(i,j),getnum(i,j-1),1);
if(j<m&&!obs[getnum(i,j+1)])addedge(getnum(i,j),getnum(i,j+1),1);
int dis=min(min(j-l[getnum(i,j)],r[getnum(i,j)]-j),min(i-u[getnum(i,j)],d[getnum(i,j)]-i));
addedge(getnum(i,j),getnum(i,l[getnum(i,j)]),dis+1);
addedge(getnum(i,j),getnum(i,r[getnum(i,j)]),dis+1);
addedge(getnum(i,j),getnum(u[getnum(i,j)],j),dis+1);
addedge(getnum(i,j),getnum(d[getnum(i,j)],j),dis+1);
}
dijkstra(s);
if(dis[t]==inf) puts("no");
else printf("%d",dis[t]);
return 0;
}
/*
6 8
########
#.##..F#
#C.##..#
#..#...#
#.....##
########
*/
T3
大概就是枚举最高点,三分高度,然后用树状数组来维护前后贡献
辣鸡南瓜码力不足