错失机会++
考试经过
T1发现是水题,和暴力拍了几下然后改改加几个特判就过了
T2不太会,看T3,发现60分比较好拿,看了一眼T4,这不是三元环?突然想写T4,于是开码,觉得空间有点悬于是卡了卡
把map
换成unordered_map
就极限数据2s了,觉得没事,然后看T3
T3立刻写了一个\(n^3\)暴力,想着60,结果发现极限数据0.2,仔细想好像是\(n^2\ln\)的,于是不管了
T2想打暴力,发现不会,部分分T了,所以最后也没拿到分
100+0+100+100=300,出分一看3个AK的马师傅\(10:30\)AK,然后开始快乐AKIOI。。。%就完事了
T1.石子合并
如果有正有负,那么一定可以构造出一种方案使得所有的贡献都是绝对值之和
全正全负就牺牲绝对值最小的变成负贡献,注意特判1
主要是数据范围会提示这样的直接扫的做法
#include <bits/stdc++.h>
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return x*f;
}
signed main()
{
freopen("stone.in","r",stdin);
freopen("stone.out","w",stdout);
int t;cin>>t;
while(t--)
{
int n=read(),mi=1e9,ans=0,cnt=0;
if(n==1){printf("%d\n",read());continue;}
for(int i=1;i<=n;i++)
{
int x=read();ans+=abs(x);mi=min(mi,abs(x));
if(x>=0)cnt++;
}
if(cnt==n||cnt==0)printf("%d\n",ans-2*mi);
else printf("%d\n",ans);
}
return 0;
}
T2.翻转游戏
当我一看见前缀后缀的时候仿佛明白了一切
求\(n-1\)个矩形的交,预处理前后缀的交,然后枚举哪个不选,最后减去\(n\)个的交
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=300050;
struct node{
int x,l,y,r;
inline bool ck()
{
if(x==0&&l==0&&r==0&&y==0)return 0;
else return 1;
}
inline int gett()
{
if(!ck())return 0;
return (y-x+1)*(r-l+1);
}
inline void print()
{
cout<<"x"<<x<<"l"<<l<<"y"<<y<<"r"<<r<<endl;
}
}a[N],b[N],c[N];
int p,q,n;
inline bool check(node p1,node p2)
{
if(p1.l>p2.l)swap(p1,p2);
if(p1.r<p2.l||p1.y<p2.x||p2.y<p1.x)return 0;
return 1;
}
inline node get(node p1,node p2)
{
if(!check(p1,p2))return (node){0,0,0,0};
return (node){max(p1.x,p2.x),max(p1.l,p2.l),min(p2.y,p1.y),min(p1.r,p2.r)};
}
inline node gan()
{
node pp=(node){1,1,(int)1e9,(int)1e9};
for(int i=1;i<=n;i++)
{
if(!check(a[i],pp))return (node){0,0,0,0};
pp=get(pp,a[i]);
}
return (pp.r==1e9)?(node){0,0,0,0}:pp;
}
signed main()
{
freopen("carpet.in", "r", stdin);
freopen("carpet.out", "w", stdout);
int T;cin>>T;
while(T--)
{
memset(b,0,sizeof(b));memset(c,0,sizeof(c));
scanf("%lld%lld%lld",&p,&q,&n);
for(int i=1;i<=n;i++)scanf("%lld%lld%lld%lld",&a[i].x,&a[i].l,&a[i].y,&a[i].r),a[i].x++,a[i].l++;
b[0]=c[n+1]=(node){0,0,(int)1e9,(int)1e9};int ans=0;
for(int i=1;i<=n;i++)b[i]=get(b[i-1],a[i]);
for(int i=n;i>=1;i--)c[i]=get(c[i+1],a[i]);
for(int i=1;i<=n;i++)ans+=get(b[i-1],c[i+1]).gett();
ans-=gan().gett()*(n-1);cout<<ans<<endl;
}
return 0;
}
感觉自己像个zz
T3.优美的旋律
枚举字符串,然后枚举他的倍数,哈希判断是否合法,复杂度\(n^2\ln n\)
可以通过打标记来优化到\(n^2\),但由于常数小已经可过
T4.基站建设
无向图三元环板子,找出来环之后判断
拿哈希表暴力存储,发现空间刚好够,然后最后枚举出答案即可
复杂度\(m\sqrt m\),自带超大常数
#include <bits/stdc++.h>
using namespace std;
#define int unsigned int
#define pir pair<int,int>
const int N=50050,M=200050;
inline int read()
{
int x=0;char ch=getchar();
while(ch<'0'||ch>'9')ch=getchar();
while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return x;
}
struct node{
int from,to,next;
}a[2*M];
int head[N],mm=1;
inline void add(int x,int y)
{
a[mm].from=x;a[mm].to=y;
a[mm].next=head[x];head[x]=mm++;
}
unordered_map <int,int> mp;
int c[450*N][2],n,m,w[N],tot,id[450*N];
inline int ganhash(int x,int y)
{
return x*50001+y;
}
inline void ganid(int x,int y,int z)
{
int idd;
if(mp.find(ganhash(x,y))!=mp.end())idd=mp[ganhash(x,y)];
else if(mp.find(ganhash(y,x))!=mp.end())idd=mp[ganhash(y,x)];
else idd=++tot,mp.insert(make_pair(ganhash(x,y),idd)),id[idd]=ganhash(x,y);
if(!c[idd][0])c[idd][0]=z;
else if(!c[idd][1])
{
c[idd][1]=z;if(w[c[idd][0]]<w[c[idd][1]])swap(c[idd][0],c[idd][1]);
}
else
{
if(w[z]<=w[c[idd][1]])return;
else if(w[z]<=w[c[idd][0]])c[idd][1]=z;
else c[idd][1]=c[idd][0],c[idd][0]=z;
}
}
inline void gan(int x,int y,int z)
{
ganid(x,y,z);ganid(x,z,y);
ganid(y,z,x);
}
int fr[M],to[M],du[N],v[N];
signed main()
{
freopen("station.in","r",stdin);
freopen("station.out","w",stdout);
cin>>n>>m;int sum=0;
for(int i=1;i<=n;i++)w[i]=read();
for(int i=1;i<=m;i++)
{
fr[i]=read(),to[i]=read();
du[fr[i]]++;du[to[i]]++;
}
for(int i=1;i<=m;i++)
{
int x=fr[i],y=to[i];
if(du[x]<du[y]||(du[x]==du[y]&&x<y))swap(x,y);
add(x,y);
}
for(int x=1;x<=n;x++)
{
for(int i=head[x];i;i=a[i].next)v[a[i].to]=x;
for(int i=head[x];i;i=a[i].next)
{
int y=a[i].to;
for(int j=head[y];j;j=a[j].next)
{
int z=a[j].to;
if(v[z]==x)gan(x,y,z);
}
}
}
int ans=0;
for(int i=1;i<=tot;i++)
{
if(!(w[c[i][0]]*w[c[i][1]]))continue;
int x=id[i]/50001,y=id[i]%50001;
ans=max(ans,w[c[i][0]]*w[c[i][1]]+(w[x]+1)*(w[y]+1));
}
cout<<ans<<endl;
return 0;
}
考试总结
思维一定要到,能做的题不要考玩才后悔
不要乱看题,很耽误时间,容易慌,要把题想进去,别犹豫