GDKOI2021 PJ Day1&2 游记

前言

加起来400分……
本着作死的心态来作死的2天


SSL初一组物品栏:
KYX:rp药 *10(Day1 220’)
WCR:擦鼻涕的纸/包扎受伤脚的纸 *inf
MYD:永远喝不完的奶粉 *inf
WJ:中午温暖的床 *1
LYW:不知道有什么诡异的东西的QQ *1

Day1

[KYX使用了rp药,rp=inf]
[KYX使用了rp药,获得成就:rp药第一人]
[KYX使用了rp药,增益状态启动]
[MYD使用奶粉,rp++]
[中午WCR的脚底受伤,rp–,使用包扎受伤脚的纸,rp++]
[中午WJ使用它/他温暖的床,rp++]
[下午LYW使用诡异的QQ,rp=-inf,将对其Day 2成绩造成影响]

T1

一道让人瞎搞的水题,记不得题面了
除了推式子一切都好
code:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
int n,sl,sh;
int a[2011][2011],i,j,ax[2*2011*2011],ay[2*2011*2011],tot;
int main()
{
 freopen("map.in","r",stdin);
 freopen("map.out","w",stdout);
 scanf("%d",&n);
 for (i=1;i<=n;i++) for (j=1;j<=n;j++)
 {
  scanf("%d",&a[i][j]);
  if (i==1||j==1) continue;
  a[i][n+1]+=a[i][j];
  a[n+1][j]+=a[i][j];
 }
 if (a[1][1]!=0)
 {
  printf("1 1");
  fclose(stdin);
  fclose(stdout);
  return 0;
 }
 sh=a[n][n+1]+a[n][1];
 sl=a[n+1][n]+a[1][n];
 int l=0,r=0;
 for (i=2;i<=n-1;i++) 
 {
  if ((a[i][n+1]+sh)%2!=a[i][1])
  {
   r++;
   for (j=2;j<=n;j++)
   {
    ay[tot]=j;
    ax[tot++]=i;
   }
  }
 }
 for (i=2;i<=n-1;i++)
 {
  if ((a[n+1][i]+sl)%2!=a[1][i])
  {
   l++;
   for (j=2;j<=n;j++)
   {
    ay[tot]=i;
    ax[tot++]=j;
   }
  }
 }
 if (l==n-2&&r==n-2)
 {
  printf("%d %d",n,n);
 }
 if (tot==n-1&&(l==0||r==0))
 {
  if (r==0) printf("1 %d",ay[tot-1]);
  else printf("%d 1",ax[tot-1]);
 }
 if (tot==2*n-2&(l==1&&r==1))
 {
  printf("%d %d",ax[0],ay[tot-1]);
 }
 if (tot==(n-1)*(n-2)&&(r==0||l==0))
 {
  if (r==0) printf("1 %d",n);
  else printf("%d 1",n);
 }
 if (tot==(n-1)*(n-2)+(n-1))
 {
  if (r==1&&l==n-2)
  {
   printf("%d %d",ax[0],n);
  }
  else
  {
   printf("%d %d",n,ay[tot-1]);
  }
 }
 fclose(stdin);
 fclose(stdout);
 return 0;
}

T2

这题叫灌水……
为什么这是Day1最难的一题??(暗示Day1很水)
不开long long见祖宗
考场时想不出?暴力真香!!
40pts的暴力,貌似5mins?
正解是单调队列+二分查找
貌似我的单调队列很诡异?
ACcode:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
long long n,q,j,o,l,r,x,y,bl,br,cl,cr;
long long a[200001],s[200001],ans[200001];
struct f{
 long long x,y;
} op;
bool cmp(f a,f b)
{
 return a.x<=b.x;
}
vector<f> d[200001];
f b[200001],c[200001];
int main()
{
 freopen("water.in","r",stdin);
 freopen("water.out","w",stdout);
 scanf("%lld%lld",&n,&q);
 for (int i=1;i<=n;i++)
 {
  scanf("%lld",&a[i]);
  s[i]=s[i-1]+a[i];
 }
 for (int i=1;i<=q;i++)
 {
  scanf("%lld%lld",&x,&y);
  op.x=y,op.y=i;
  d[x].push_back(op);
 }
 bl=br=n;
 b[bl].x=0x7ffffff;
 b[bl--].y=0;
 for (int i=1;i<=n;i++)
 {
  cl=cr=n;
  c[cl].x=0x7ffffff;
  c[cl--].y=n+1;
  while (bl<br&&b[bl+1].x<a[i]) bl++;
  b[bl].x=a[i];
  b[bl--].y=i;
  for (int j=n;j>=i;j--)
  {
   while (cl<cr&&c[cl+1].x<a[j]) cl++;
   c[cl].x=a[j];
   c[cl--].y=j;
  }
  for (int j=0;j<d[i].size();j++)
  {
   op=d[i][j];
   ans[op.y]=op.x*((c[upper_bound(c+cl,c+n+1,op,cmp)-c].y-1)-(b[upper_bound(b+bl,b+br,op,cmp)-b].y))-s[c[upper_bound(c+cl,c+n+1,op,cmp)-c].y-1]+s[b[upper_bound(b+bl,b+br,op,cmp)-b].y];
  }
 }
 for (int i=1;i<=q;i++) cout<<ans[i]<<endl;
 fclose(stdin);
 fclose(stdout);
 return 0;
}

T3

大概是说把n个数两两(凉凉)配对,(>=l&<=r)求无法配对的个数
不会?
没事,增广路教他做人
实测考场时仅次于正解贪心,60pts(一看就是我的算法太诡异搞得出题人木有卡
纪念增广路code:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
int n,L,R,mn=0x7ffffff+1,mx,a[1000001],to[1000001],ans,x;
bool op[1000001];
bool dfs(int r)
{
 for (int i=1;i<=n;i++)
 {
  if (a[i]+a[r]<=R&&a[i]+a[r]>=L&&op[i]==0)
  {
   if (to[i]==0)
   {
    to[i]=r,to[r]=i;
    return 1;
   }
   else
   {
    op[i]=1; 
    int u=to[i];
    op[u]=1;
    to[i]=r,to[r]=i;
    to[u]=0;
    if (dfs(u)) return 1;
    to[i]=u,to[u]=i,to[r]=0;
   }
  }
 }
 return 0;
}
int main()
{
 freopen("match.in","r",stdin);
 freopen("match.out","w",stdout);
 scanf("%d%d%d",&n,&L,&R);
 for (int i=1;i<=n;i++)
 {
  scanf("%d",&a[i]);
  if (a[i]<mn) mn=a[i];
 }
 for (int i=1;i<=n;i++)
 {
  if (R-mn>=a[i]&&to[i]==0)
  {
   memset(op,0,sizeof(op));
   op[i]=1;
   x=i;
   dfs(i);
  }
 }
 for (int i=1;i<=n;i++)
 {
  if (to[i]==0) ans++;
 }
 printf("%d",ans);
 fclose(stdin);
 fclose(stdout);
 return 0;
}

ACcodes:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
int n,L,R,l,r,a[1000001],to[1000001],s;
int main()
{
 freopen("match.in","r",stdin);
 freopen("match.out","w",stdout);
 scanf("%d%d%d",&n,&L,&R);
 for (int i=1;i<=n;i++)
 {
  scanf("%d",&a[i]);
 }
 sort(a+1,a+1+n);
 r=n,l=1;
 while (l<=r)
 {
  if (a[l]+a[r]<L) l++;
  else if (a[l]+a[r]>R) r--;
  else l++,r--,s+=2;
 }
 printf("%d",n-s);
 fclose(stdin);
 fclose(stdout);
 return 0;
}//请诸位对比代码长度

T4

为啥dij和spfa不给分?是不是看不起最短路
其实就是并查集,不过查询和合并的顺序要搞一下
ACcodes:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
int n,m,q,x,y,wy,ans,fa[200001],question[200001],b[200001];
struct f{
 int x,y,z;
} a[610001];
int max(int x,int y)
{
 if (x>y) return x;
 else return y;
}
int find(int x)
{
 if (fa[x]==x) return x;
 else return fa[x]=find(fa[x]);
}
bool cmp(f a,f b)
{
 if (a.z==b.z) return a.y>b.y;
 return a.z<b.z;
}
int main()
{
 freopen("travel.in","r",stdin);
 freopen("travel.out","w",stdout);
 scanf("%d%d",&n,&m);
 for (int i=1;i<=n;i++) b[i]=1,fa[i]=i;
 for (int i=1;i<=m;i++)
 {
  scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);
 }
 scanf("%d",&q);
 for (int i=1;i<=q;i++)
 {
  scanf("%d%d",&a[i+m].x,&a[i+m].z);
  a[i+m].y=-i;
 }
 sort(a+1,a+1+m+q,cmp);
 for (int i=1;i<=m+q;i++)
 {
  if (a[i].y>=0)
  {
   if (find(a[i].x)!=find(a[i].y)) b[find(a[i].y)]+=b[find(a[i].x)],fa[find(a[i].x)]=find(a[i].y);
  }
  else
  {
   question[-a[i].y]=b[find(a[i].x)];
  }
 }
 for (int i=1;i<=q;i++) cout<<question[i]<<endl;
 fclose(stdin);
 fclose(stdout);
 return 0;
}

Day 2

[WCR脚修复完成,感冒,rp–,使用擦鼻涕的纸,rp++]
[MYD使用奶粉,rp++,增益状态启动]
[LYW减益状态启动]
[KYXrp药产生副作用,减益状态启动]
[中午WJ使用温暖的床,白日梦++,增益状态启动]
[WJ白日梦数量达到1,获得成就:与周公约会]
[周公吸走WJrp,WJrp=-1]
[周公传授WJ秘籍《乱卡精度》,需要增益状态使用]
[WJrp<0,增益取消,减益状态启动]

T1

有手就行
小四做过的题,忙里偷闲打了个快速幂
code:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
int a[11];
int x=1;
int uyu(int x,int y)
{
 int ans=1;
 while (y!=0)
 {
  if (y%2==0)
  {
   y/=2;
   x*=x;
   x%=10;
  }
  else
  {
   y--;
   ans*=x;
   ans%=10;
  }
 }
 return ans;
}
int main()
{
 freopen("math.in","r",stdin);
 freopen("math.out","w",stdout);
 for (int i=1;i<=10;i++) cin>>a[i];
 for (int i=8;i>=4;i-=2)
 {
  if (a[i]!=0)
  {
   a[i/2]+=a[i];
   a[2]+=a[i];
   a[i]=0;
  }
 }
 int l=abs(a[2]-a[5]);
 if (a[2]>a[5]) a[5]=0,a[2]=l;
 else a[5]=l,a[2]=0;
 for (int i=9;i>=2;i--)
 {
  x=(x*uyu(i,a[i]))%10;
 }
 cout<<x;
 fclose(stdin);
 fclose(stdout);
 return 0;
}

T2

据说因为评测机太快(数据太水)导致我一个把bfs序看成dfs序的人AC,显然算法是一样的,但是bfs可以o(n),真是作死
code:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
int t,n,fa[100001],tot,a[100001],i,zy[100001],zuo[100001],you[100001];
bool o;
inline int read()
{
 int ans=0;
 char u=getchar();
 while (u>'9'||u<'0') u=getchar();
 while (u<='9'&&u>='0') ans=ans*10+u-'0',u=getchar();
 return ans;
}
bool dfs(int father)
{
 if (father==0) return 0;
 if (zy[father]==0)
 {
  if (a[i]<a[father])
  {
   zy[father]=1;
   fa[i]=father;
   zuo[father]=i;
   return 1;
  }
  else
  {
   return 0;
  }
 }
 if (zy[father]==1)
 {
  if (a[i]>a[father])
  {
   zy[father]=2;
   fa[i]=father;
   you[father]=i;
   return 1;
  }
  else
  {
   if (dfs(zuo[father])==1)
   {
    return 1;
   }
   return 0;
  }
 }
 if (zy[father]==2)
 {
  if (a[i]<a[father])
  {
   if (dfs(zuo[father])==1)
   {
    return 1;
   }
  }
  if (a[i]>a[father])
  {
   if (dfs(you[father])==1)
   {
    return 1;
   }
  }
  return 0;
 }
}//作而不死,是为rp--
int main()
{
 freopen("tree.in","r",stdin);
 freopen("tree.out","w",stdout);
 t=read();
 while (t--)
 {
  memset(zy,0,sizeof(zy));
  memset(fa,0,sizeof(fa));
  n=read();
  tot=1;
  o=0;
  a[1]=read();
  for (i=2;i<=n;i++)
  {
   a[i]=read();
   if (o==1) continue;
   if (!dfs(1)) o=1;//Do you know DFS?
  }
  if (o) printf("NO\n");
  else printf("YES\n");
 }
 fclose(stdin);
 fclose(stdout);
 return 0;
}

T3

最崩溃的是知道怎么做,但是就是打不出来
LCA+倍增+树上dp,先咕了,等学了LCA再做

T4

话说为啥dfs不给分?(5分都没有,真是作死)
实际上是开了spj(据说)的,那么我们先对半分,然后欧拉回路判断奇偶性,嗯,就这样了,嗯,嗯……
ACcode:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
int n,a[1001][1001],b[1001][1001],c[1001][1001],o;
void dfs(int x)
{
 if (o==0)
 {
  for (int i=1;i<=n;i++)
  {
   if (a[x][i])
   {
    a[x][i]=0;
    o=1;
    c[x][i]++;
    dfs(i);
    return;
   }
  }
 }
 else
 {
  for (int i=1;i<=n;i++)
  {
   if (a[i][x])
   {
    a[i][x]=0;
    o=0;
    b[i][x]++;
    dfs(i);
    return;
   }
  }
 }
 return;
}//发现a数组%2后就是一个邻接矩阵,不用白不用
int main()
{
 freopen("matrix.in","r",stdin);
 freopen("matrix.out","w",stdout);
 scanf("%d",&n);
 for (int i=1;i<=n;i++) for (int j=1;j<=n;j++)
 {
  scanf("%d",&a[i][j]);
  b[i][j]=c[i][j]=a[i][j]/2;
  a[i][j]%=2;
 }
 for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) if (a[i][j])
 {
  a[i][j]=0;
  b[i][j]++;
  o=0;
  dfs(j);
  break; 
 }
 for (int i=1;i<=n;i++)
 {
  for (int j=1;j<=n;j++) printf("%d ",b[i][j]);
  printf("\n");
 }
 for (int i=1;i<=n;i++)
 {
  for (int j=1;j<=n;j++) printf("%d ",c[i][j]);
  printf("\n");
 }
 fclose(stdin);
 fclose(stdout);
 return 0;
}

后记

天知道我在哪个多重宇宙里,也许是AK的,也许是爆零的。——WCR
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值