noip模拟37[我非常的爽]
noip模拟37 solutions
为什么爽呢??因为我这个状态极佳,但是考得不好
就是爽,没有理由的爽,因为思想淋漓尽致。每一点都考虑到了
考了4个题但是这个题也太水了吧。。。。。虽然我没有A
就是几分种就能改完的那种,有的是傻瓜题,有的是原题,后两个还是有水平。。。
我做不出来我还是要吐嘈。。。。。
T1 数列
简简单单的exgcd好吧,太强了
我只不过是考场上手动加了一个n而已,T了而已
没关系,稍微一改就过了
注意这里有一些小细节,强制所有的都是正数,强制a<b
解得的x,y的变化范围是b/gcd,a/gcd;
AC_code
#include<bits/stdc++.h>
using namespace std;
#define re register int
#define ll long long
const int N=1e5+5;
ll n,a,b,xl[N],ys;
struct node{
ll x,y,sum;
};
node exgcd(ll s,ll t){
node u,v;
if(t==0){
v.sum=s;
v.x=1;
v.y=0;
return v;
}
u=exgcd(t,s%t);
v.sum=u.sum;
v.x=u.y;
v.y=u.x-s/t*u.y;
return v;
}
ll out;
signed main(){
scanf("%lld%lld%lld",&n,&a,&b);
for(re i=1;i<=n;i++)scanf("%lld",&xl[i]),xl[i]=abs(xl[i]);
a=abs(a);b=abs(b);
if(a>b)swap(a,b);
//cout<<a<<" "<<b<<endl;
node ans=exgcd(a,b);
a/=ans.sum;b/=ans.sum;
bool flag=false;
for(re i=1;i<=n;i++){
if(xl[i]%ans.sum){
flag=true;break;
}
xl[i]/=ans.sum;
ys=xl[i]%b;
ll x=ans.x*(ys);
ll y=ans.y*(ys)+xl[i]/b;
//cout<<x<<" "<<y<<endl;
ll su=abs(x)+abs(y);
if(x>0){
ll s=abs(x)/b;
x-=s*b;
y+=s*a;
su=min(su,abs(x)+abs(y));
su=min(su,abs(x-b)+abs(y+a));
}
else if(x<0){
ll s=abs(x)/b;
x+=s*b;
y-=s*a;
su=min(su,abs(x)+abs(y));
su=min(su,abs(x+b)+abs(y-a));
}
out+=su;
//if(i==1)cout<<su<<endl;
}
if(flag)printf("-1");
else printf("%lld",out);
}
T2 数对
这个题就是打乱顺序的‘队长快跑’
所以这个题只要你排好序了,这个题你就A了
考场上我觉得这个题不可做就跑路了
其实我们只需要对a+b的大小排序就好了
自己手动模拟一下就好了,一共就四种情况,有两种完全没有影响,有两种只和a+b有关
就先高潮来一个\(\mathcal{O(n^2)}\)的dp,用线段树维护就好了
60RE
#include<bits/stdc++.h>
using namespace std;
#define re register int
#define int long long
const int N=1e5+5;
int n;
struct node{
int a,b,w;
bool operator < (node x)const{
return a+b<x.a+x.b;
}
}sca[N];
int f[3005][6005],ans;
int lsh[N],lh;
signed main(){
scanf("%lld",&n);
for(re i=1;i<=n;i++){
scanf("%lld%lld%lld",&sca[i].a,&sca[i].b,&sca[i].w);
lsh[++lh]=sca[i].a;lsh[++lh]=sca[i].b;
}
sort(lsh+1,lsh+lh+1);
lh=unique(lsh+1,lsh+lh+1)-lsh-1;
for(re i=1;i<=n;i++){
sca[i].a=lower_bound(lsh+1,lsh+lh+1,sca[i].a)-lsh;
sca[i].b=lower_bound(lsh+1,lsh+lh+1,sca[i].b)-lsh;
}
sort(sca+1,sca+n+1);
f[0][0]=0;
for(re i=1;i<=n;i++){
//cout<<sca[i].a<<" "<<sca[i].b<<" "<<sca[i].w<<endl;
for(re j=0;j<=lh;j++)f[i][j]=f[i-1][j];
for(re j=0;j<=min(sca[i].b,sca[i].a);j++)
f[i][sca[i].a]=max(f[i][sca[i].a],f[i-1][j]+sca[i].w);
for(re j=sca[i].a+1;j<=sca[i].b;j++)
f[i][j]=max(f[i][j],f[i-1][j]+sca[i].w);
}
for(re i=1;i<=lh;i++)ans=max(ans,f[n][i]);
printf("%lld",ans);
}
AC_code
#include<bits/stdc++.h>
using namespace std;
#define re register int
#define ll long long
const int N=1e5+5;
int n;
struct node{
ll a,b,w;
node(){}
bool operator < (node x)const{
return a+b<x.a+x.b;
}
}sca[N];
ll lsh[N*2],lh;
struct XDS{
#define ls x<<1
#define rs x<<1|1
ll tr[N*8],laz[N*8];
void pushup(int x){
tr[x]=max(tr[ls],tr[rs]);
return ;
}
void pushdown(int x){
if(!laz[x])return ;
laz[ls]+=laz[x];
tr[ls]+=laz[x];
laz[rs]+=laz[x];
tr[rs]+=laz[x];
laz[x]=0;
return ;
}
void ins_pot(int x,int l,int r,int pos,ll v){
if(l==r){
tr[x]=max(tr[x],v);
return ;
}
pushdown(x);
int mid=l+r>>1;
if(pos<=mid)ins_pot(ls,l,mid,pos,v);
else ins_pot(rs,mid+1,r,pos,v);
pushup(x);return ;
}
void ins_inr(int x,int l,int r,int ql,int qr,ll v){
if(ql<=l&&r<=qr){
laz[x]+=v;tr[x]+=v;
return ;
}
pushdown(x);
int mid=l+r>>1;
if(ql<=mid)ins_inr(ls,l,mid,ql,qr,v);
if(qr>mid)ins_inr(rs,mid+1,r,ql,qr,v);
pushup(x);return ;
}
ll query(int x,int l,int r,int ql,int qr){
if(ql<=l&&r<=qr)return tr[x];
pushdown(x);
int mid=l+r>>1;ll ret=0;
if(ql<=mid)ret=max(ret,query(ls,l,mid,ql,qr));
if(qr>mid)ret=max(ret,query(rs,mid+1,r,ql,qr));
pushup(x);
return ret;
}
#undef ls
#undef rs
}xds;
ll ans;
signed main(){
scanf("%d",&n);
for(re i=1;i<=n;i++){
scanf("%lld%lld%lld",&sca[i].a,&sca[i].b,&sca[i].w);
lsh[++lh]=sca[i].a;lsh[++lh]=sca[i].b;
}
sort(sca+1,sca+n+1);
sort(lsh+1,lsh+lh+1);
lh=unique(lsh+1,lsh+lh+1)-lsh-1;
for(re i=1;i<=n;i++){
sca[i].a=lower_bound(lsh+1,lsh+lh+1,sca[i].a)-lsh;
sca[i].b=lower_bound(lsh+1,lsh+lh+1,sca[i].b)-lsh;
}
//sort(sca+1,sca+n+1);
for(re i=1;i<=n;i++){
xds.ins_inr(1,1,lh,sca[i].a+1,sca[i].b,sca[i].w);
ll tmp=xds.query(1,1,lh,1,min(sca[i].a,sca[i].b))+sca[i].w;
xds.ins_pot(1,1,lh,sca[i].a,tmp);
//xds.ins_inr(1,1,lh,sca[i].a+1,sca[i].b,sca[i].w);
}
printf("%lld",xds.tr[1]);
}
T3 最短路
就是用dij跑一个多源最短路就好了,
直接将所有的特殊点压到队列中,以这些点作为起点来跑最短路
得到的是所有非特殊点的距离最近的特殊点的距离
那么我们继续枚举每一个边,这两条边所链接的两个点如果最近的特殊点不一样就可以直接更新
这样正确性是有保证的,因为你两个特殊点要么是直接相连,要么是通过一个非特殊点相连
而当前非特殊点的最近的特殊点已经被你处理出来了,
AC_code
#include<bits/stdc++.h>
using namespace std;
#define re register int
#define ll long long
const int N=2e5+5;
int n,m,p,spc[N];
struct node{
ll dis,who;
node(){}
node(ll x,ll y){
dis=x;who=y;
}
bool operator < (node x)const{
return dis>x.dis;
}
};
priority_queue<node> q;
struct edge{
ll x,y,w;
}sca[N];
ll dit[N],whe[N],ans[N];
int to[N*2],nxt[N*2],head[N],rp;
ll val[N*2];
void add_edg(int x,int y,ll z){
to[++rp]=y;
val[rp]=z;
nxt[rp]=head[x];
head[x]=rp;
}
bool vis[N];
signed main(){
memset(dit,0x3f,sizeof(dit));
scanf("%d%d%d",&n,&m,&p);
for(re i=1;i<=p;i++){
scanf("%d",&spc[i]);
dit[spc[i]]=0;whe[spc[i]]=spc[i];
ans[spc[i]]=0x3f3f3f3f3f3f3f;
q.push(node(0,spc[i]));
}
for(re i=1;i<=m;i++){
scanf("%lld%lld%lld",&sca[i].x,&sca[i].y,&sca[i].w);
add_edg(sca[i].x,sca[i].y,sca[i].w);
add_edg(sca[i].y,sca[i].x,sca[i].w);
}
while(!q.empty()){
int dis=q.top().dis,who=q.top().who;q.pop();
if(vis[who])continue;vis[who]=true;
for(re i=head[who];i;i=nxt[i]){
int y=to[i];//if(vis[y])continue;
if(dis+val[i]>dit[y])continue;
dit[y]=dis+val[i];whe[y]=whe[who];
q.push(node(dit[y],y));
}
}
for(re i=1;i<=m;i++){
if(whe[sca[i].x]==whe[sca[i].y])continue;
ll tmp=dit[sca[i].x]+dit[sca[i].y]+sca[i].w;
if(ans[whe[sca[i].x]]>tmp)ans[whe[sca[i].x]]=tmp;
if(ans[whe[sca[i].y]]>tmp)ans[whe[sca[i].y]]=tmp;
}
for(re i=1;i<=p;i++)printf("%lld ",ans[spc[i]]);
}
T4 真相
这个题我考场上又想麻烦了,拿着并查集就去维护了
不如说少想了一些情况。。。
首先没有第一种的情况,直接从第一个开始走,遇到3就给当前的now^1,
这样如果到最后还是1的话,那就合法,
如果有第一种话,那么这个序列一定可以被这些人,分成许多块,
我们可以统计这些块内当说第一种话的人真的时候,说真话和假话的人的个数
就完了
AC_code
#include<bits/stdc++.h>
using namespace std;
#define re register int
const int N=1e6+5;
int T,n;
struct node{
int typ,num;
node(){}
}sca[N*2];
int sta[N],top;
int ji[N],cnt;
int f[N][2],g[N][2],sum;
signed main(){
scanf("%d",&T);
while(T--){
top=0;cnt=0;sum=0;
//memset(g,0,sizeof(g));
scanf("%d",&n);
for(re i=1;i<=n;i++){
char a[5];scanf("%s",a);
if(a[0]=='$'){
sca[i].typ=1;
scanf("%d",&sca[i].num);
sta[++top]=i;
}
if(a[0]=='+')sca[i].typ=2;
if(a[0]=='-')sca[i].typ=3;
}
//cout<<top<<endl;
if(!top){
int now=1;
for(re i=1;i<=n;i++)if(sca[i].typ==3)now^=1;
if(now==0)printf("inconsistent\n");
else printf("consistent\n");
}
else{
for(re i=1;i<=top;i++){
int fro=sta[i]+1,beh,tru=0,siz=1,now=1;
if(i==top)beh=sta[1];
else beh=sta[i+1];
if(fro>n)fro-=n;
for(re j=fro;j!=beh;){
if(now)tru++;
if(sca[j].typ==3)now^=1;
siz++;j++;
if(j>n)j-=n;
}
ji[++cnt]=sca[beh].num;
if(now){
tru++;
f[cnt][1]=tru;
f[cnt][0]=siz-tru;
}
else{
f[cnt][1]=siz-tru;
f[cnt][0]=tru;
}
g[ji[cnt]][1]+=f[cnt][1];
g[ji[cnt]][0]+=f[cnt][0];
sum+=f[cnt][0];
}
bool flag=false;
for(re i=0;i<=n;i++){
int tmp=sum-g[i][0]+g[i][1];
if(tmp==i){flag=true;break;}
}
if(flag)printf("consistent\n");
else printf("inconsistent\n");
for(re i=1;i<=cnt;i++)g[ji[i]][0]=g[ji[i]][1]=0;
}
}
}
QQ:2953174821