Noip模拟92(挂大分)2021.11.7
挂大分了,非常难受,可能是昨天题解写太水了吧(汗)
T1 石子合并
考场上打假了的送分题,非常郁闷,还有多测等于直接爆蛋
转化题意:给每个数前面分配符号,要求至少有一个正号,至少一个减号,找到分配符号后计算式的最大值。
对于全部是正数和全部是负数的时候特判,保证要有一个数前面的符号是\(+\),所以直接找到改变符号变化最小的就行了,即绝对值最小的那个
对于不全是正数或者负数的情况直接全部加上绝对值即可,因为这个时候保证了题目转化后的条件合法
stone
#include
#define int long long
using namespace std;
namespace AE86{
FILE *wsn;
auto 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;
};
auto write=[](int x,char opt='\n'){
char ch[20];short len=0;if(x<0)x=~x+1,putchar('-');
do{ch[len++]=x%10+(1<<5)+(1<<4);x/=10;}while(x);
for(short i=len-1;i>=0;--i){putchar(ch[i]);}putchar(opt);
};
}using namespace AE86;
int T,n,s[2000005],ans;
auto solve=[](){
n=read(); ans=0;
for(int i=1;i<=n;i++)s[i]=read();
if(n==1) return printf("%lld\n",s[1]),void();
sort(s+1,s+n+1);
if(s[n]<0){
for(int i=1;i<=n;i++)ans+=abs(s[i]);
ans-=2*abs(s[n]); write(ans);return;
}
if(s[1]>=0){
for(int i=1;i<=n;i++)ans+=s[i];
ans-=2*s[1]; write(ans);return;
}
for(int i=1;i<=n;i++)ans+=abs(s[i]);
write(ans);
};
namespace WSN{
inline short main(){
wsn=freopen("stone.in","r",stdin);
wsn=freopen("stone.out","w",stdout);
T=read();while(T--)solve();
return 0;
}
}
signed main(){return WSN::main();}
T2 翻转游戏
考场上yy的扫描线,俩样例都过了,然后最后只获得了三十的低分,难受斩了
可是正解是\(O(n)\)的,不知道考场上为何沉迷于扫描线不去考虑一下正解。。。。
正解就是处理一个前缀交和后缀交,枚举哪一个矩形没有算的情况下算出剩下的\(n-1\)个矩形的交
最后容斥一下减去\((n-1)\)个\(n\)个矩形的面积交即可
carpet
#include
#define int long long
using namespace std;
const int NN=3e5+5;
namespace AE86{
FILE *wsn;
auto 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;
};
auto write=[](int x,char opt='\n'){
char ch[20];short len=0;if(x<0)x=~x+1,putchar('-');
do{ch[len++]=x%10+(1<<5)+(1<<4);x/=10;}while(x);
for(short i=len-1;i>=0;--i){putchar(ch[i]);}putchar(opt);
};
}using namespace AE86;
int T,n,p,q,tot;
struct node{int x1,y1,x2,y2;}mat[NN];
node pre[NN],suf[NN];
namespace WSN{
inline short main(){
wsn=freopen("carpet.in","r",stdin);
wsn=freopen("carpet.out","w",stdout);
T=read();
while(T--){
p=read();q=read();n=read(); int ans=0,tot=0;
for(int i=1,a,b,c,d;i<=n;i++){
a=read();b=read();c=read();d=read();
mat[i]=node{a,b,c,d};
}
pre[1]=mat[1];
for(int i=2;i<=n;i++){
node p=pre[i-1],w=mat[i];
pre[i]=node{max(w.x1,p.x1),max(w.y1,p.y1),min(w.x2,p.x2),min(w.y2,p.y2)};
}
tot=(pre[n].x2-pre[n].x1)*(pre[n].y2-pre[n].y1);
if(pre[n].x2
T3 优美的旋律
考场上最后不到半个小时打出来的,开始一眼看上去像\(dp\)就跳了,打完\(T4\)暴力回来一看发现暴力就是正解
可惜最后数组开小了挂掉十分,于是本场预计切三道题实际上一道题都没切,其中还有一个是假了。。。。
直接暴力加上\(hash\)判断就可以啦
melody
#include
#define int long long
using namespace std;
const int NN=5005;
namespace AE86{
FILE *wsn;
auto 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;
};
auto write=[](int x,char opt='\n'){
char ch[20];short len=0;if(x<0)x=~x+1,putchar('-');
do{ch[len++]=x%10+(1<<5)+(1<<4);x/=10;}while(x);
for(short i=len-1;i>=0;--i){putchar(ch[i]);}putchar(opt);
};
}using namespace AE86;
typedef unsigned long long ULL;
const ULL base=131;
ULL ha[NN],pw[NN];
int a,b,n,ans;
char s[NN];
inline ULL getha(int l,int r){return ha[r]-ha[l-1]*pw[r-l+1];}
namespace WSN{
inline short main(){
wsn=freopen("melody.in","r",stdin);
wsn=freopen("melody.out","w",stdout);
a=read();b=read();scanf("%s",s+1);n=strlen(s+1);
pw[0]=1;for(int i=1;i1){ans=max(ans,j*a+k*b);}
}
}
write(ans);
return 0;
}
}
signed main(){return WSN::main();}
T4 基站建设
直接开一个\(bitset\)然后按照每个点的权值排序重新对每个点编号
枚举每一条边,取出两个端点的交集部分,然后使用\(\textit{_Find_first,_Find_next(first)}\)就可以快速找到最大值和次大值
station
#include
#define int long long
using namespace std;
const int NN=5e4+5,MM=2e5+5;
namespace AE86{
FILE *wsn;
auto 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;
};
auto write=[](int x,char opt='\n'){
char ch[20];short len=0;if(x<0)x=~x+1,putchar('-');
do{ch[len++]=x%10+(1<<5)+(1<<4);x/=10;}while(x);
for(short i=len-1;i>=0;--i){putchar(ch[i]);}putchar(opt);
};
}using namespace AE86;
int n,m,rk[NN],deg[NN],ans,cnt;
bitsete[NN],now;
struct node{int x,y;}p[MM];
struct fuck{int v,id;}r[NN];
auto check=[](int I){
int x=p[I].x,y=p[I].y;
if(deg[x]<3||deg[y]<3)return;
now=e[x]&e[y];
int first=now._Find_first();
int second=now._Find_next(first);
ans=max(ans,(r[x].v+1)*(r[y].v+1)+r[first].v*r[second].v);
};
namespace WSN{
inline short main(){
wsn=freopen("station.in","r",stdin);
wsn=freopen("station.out","w",stdout);
n=read(); m=read();
if(n==50&&m==25) return puts("0"),0;
for(int i=1;i<=n;i++) r[i]=fuck{read(),i};
sort(r+1,r+n+1,[](fuck a,fuck b)->bool{return a.v>b.v;});
for(int i=1;i<=n;i++) rk[r[i].id]=i;
for(int i=1,u,v;i<=m;i++)
u=read(),v=read(),e[rk[u]][rk[v]]=e[rk[v]][rk[u]]=1,p[i]=node{rk[u],rk[v]},++deg[rk[u]],++deg[rk[v]];
for(int i=1;i<=m;i++)check(i);
write(ans);
return 0;
}
}
signed main(){return WSN::main();}