- 前言
- 一 Poly
- 1.题目
- 2.思路
- 3.代码
- 二 Preview
- 1.题目
- 2.思路
- 3.代码
- 三 String
- 1.题目
- 2.思路
- 3.代码
- 四 Travel
- 1.题目
- 2.思路
- 3.代码
- 五 大富翁
- 1.题目
- 2.思路
- 3.代码
- 六 真假英雄
- 1.题目
- 2.思路
- 3.代码
最近也那halo做了个个人博客,欢迎小伙伴来玩,虽然现在内容较少,但以后会多的(保证不咕咕咕,我逃)
博客地址
首先明确一点坐标点都是整数点且周长为整数:即任意一条边长都为整数
边尽可能少:只用枚举划分成三角形或者四边形的情况(我猜的,但对了2333)
然后就直接分情况讨论即可
1.C==3时,只有1,1,1的三角形,所以ans=0;
2.C>3&&C%2=1时,因为周长为奇数,所以至少是存在一条边(奇数条)的长度为奇数。我们随便取一条边L,设端点分别为(x1,y1)与(x2,y2) ,所以边长L^2 =(x1-x2)^2 +(y1-y2)^2;
若L为偶数,则|x1-x2|与|y1-y2|同偶or同奇,所以从(x1,y1)走到(x2,y2),移动点的x+y的奇偶不会发生改变
同理可得L为奇数的时候会发生改变
所以我们让移动点绕多边形转圈圈可以发现如果存在这样的多边形x+y的奇偶会发生改变,但现实是我们在转圈圈,奇偶并不会发生改变,所以可证得这样的多边形不存在
3.所以综上我们可得到只存在周长为偶数且大于3的多边形,观察数据范围是【3,5000】,可以直接暴力枚举第一象限,这里我规定的是一个点为原点,枚举另外两个点
#include#include #include #include using namespace std; const int N=2e5+10; int c,c_cur,max_L,min_L,w,cur,res=0x3f; int x[N],y[N],l[N],idx=0; bool can_line(int i, int j) { if(cur*cur==w&&cur<=c_cur&&l[i]+l[j]==c-cur&&x[i]*y[j]>y[i]*x[j]){ return true; }else return false; } int dis(int i,int j) { w=(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]); return sqrt(w); } int main() { cin>>c; if(c%2==1||c==3){ cout<<"-1"< >1; for(int i=1;1<=c;i++){ for(int j=0;i*i+j*j<=c_cur*c_cur;j++){ cur=sqrt(i*i+j*j); if(cur*cur==i*i+j*j){ l[++idx]=cur,x[idx]=i,y[idx]=j; } } } for(int i=1;i<=idx;i++){ for(int j=i+1;j<=idx&&l[i]+l[j] cur=dis(i,j); if(can_line(i,j)){ min_L=min(cur,min(l[i],l[j])); max_L=max(cur,max(l[i],l[j])); res=min(max_L-min_L,res); } } } if(res==0x3f3f3f3f){ if(c%4==0) res=0; else res=1; } cout< 二 Preview 1.题目 2.思路 一眼dp,但是那个时候还没听y总的dp降维,二维dp的o(n^2)炸了
3.代码
f[i][j]:表示复习后i门课程,从第j天开始的总价值(i>=j)
(降维我这里就不细说了,具体看别的文章,因为我也讲不太明白,自己都是玄学dp,hhhh)for(int i=n;i>=1;--i) for(int j=i-a[i];j<=i+a[i];++j) { if(j<0) continue; dp[j]=dp[j]; if(j<=i) dp[j]=max(dp[j],dp[i+a[i]+1]+a[i]*b[i]); }三 String 1.题目 2.思路累加匹配的后缀,因为只能往队头移动
3.代码#include#define ll long long using namespace std; int n; string s1,s2; int main(){ cin>>n; cin>>s1>>s2; s1="#"+s1; s2="#"+s2; int m=n,ans=0; for(int i=n;i>=1;i--){ if(s1[i]==s2[m]){ ans++; m--; } } cout< 四 Travel 1.题目 2.思路 两个思路:
①分层图最短路(注意有的题会卡spfa,我觉得用dijkstra稳妥点)
②dp+dijkstra
这里就说一下分层图的做法:分层图的核心我个人理解就是把原图平行k次,多添加了上一层到下一层的费用为0的边,然后和普通的最短路问题一样了
3.代码
这里注意可能k次免费可能并没有用完#include#include #include #include #include #include using namespace std; typedef pair PII; const int N=2e7+10; int h[N],e[N],w[N],ne[N],idx; int dis[N],min_val=N; bool st[N]; int n,m,k; struct yz{ int y,z; }; bool operator < (yz i,yz j) { if((i.z-1)/n!=(j.z-1)/n) return (i.z-1)/n>(j.z-1)/n; return i.z>j.z; } void add(int a,int b,int c){ e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++; } void Dijkstra(){ memset(dis,0x3f,sizeof dis); dis[1]=0; priority_queue heap; heap.push(yz{1,0}); while(heap.size()){ int t=heap.top().y; heap.pop(); if(st[t]) continue; st[t]=true; for(int i=h[t];i!=-1;i=ne[i]){ int j=e[i]; if(dis[j]>dis[t]+w[i]){ dis[j]=dis[t]+w[i]; heap.push(yz{j,dis[j]}); } } } } int main(){ memset(h,-1,sizeof h); cin>>n>>m>>k; int x=m; while(x--){ int a,b,c; cin>>a>>b>>c; for(int i=0;i<=k;i++){ add(i*n+a,i*n+b,c),add(i*n+b,i*n+a,c); } for(int i=0;i add(i*n+a,(i+1)*n+b,0),add(i*n+b,(i+1)*n+a,0); } } Dijkstra(); for(int i=k;i>=0;i--){ min_val=min(min_val,dis[i*n+n]); } cout< 五 大富翁 1.题目 2.思路 签到题
3.代码#include#include #include using namespace std; const int N=2e5+100; bool f[N]; int arr[N]; int main() { f[1]=true; int n; cin>>n; for(int i=1;i<=n;++i){ scanf("%d",&arr[i]); } for(int i=1;i<=n;++i){ if(f[i])for(int k=1;k<=arr[i];++k){ f[i+k]=1; } } int ans=0; for(int i=1;i<=N-10;++i){ if(f[i])ans=max(ans,i); } cout< 六 真假英雄 1.题目 2.思路 并查集的题,也比较划水,可以去做做洛谷上的食物链那题
3.代码#includeusing namespace std; const int N=1e6+5; int fa[N],sz[N],n,m,ans; int read(){ int x=0,w=1;char ch=getchar(); while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();} while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar(); return x*w; } int find(int x){ if(fa[x]==x)return fa[x]; fa[x]=find(fa[x]); sz[fa[x]]+=sz[x]; sz[x]=0; return fa[x]; } void mer(int x,int y){ int fx=find(x),fy=find(y); if(fx!=fy){ sz[fx]+=sz[fy];sz[fy]=0; fa[fy]=fx; } } //以上是并查集 int main(){ n=read();m=read();ans=0; for(int i=1;i<=2*n;i++)fa[i]=i; for(int i=1;i<=n;i++)sz[i]=0; for(int i=1+n;i<=2*n;i++)sz[i]=1;//预处理 for(int i=1;i<=m;i++){ int x=read(),y=read(); int fx=find(x),fy=find(y),fxn=find(x+n),fyn=find(y+n);//假定x,y表示坏人,x+n,y+n表示好人 string ch;cin>>ch; if(ch=="good"){ mer(x,y);mer(y+n,x+n);//如果x说y是好人,则x,y要么同时是好人,要么同时是坏人 }else { mer(x+n,y);mer(y+n,x);//如果x说y是坏人,则x,y一定有一好一坏的情况 } } for(int i=1;i<=n;i++){ if(find(i)==find(i+n)){cout<<-1< ans+=max(sz[find(i)],sz[find(i+n)]);//统计答案 ,取max是因为贪心取最大就好,因为两个不同条件的成立带来的影响是不一样的 sz[find(i)]=sz[find(i+n)]=0;//注意清0,因为之前已经统计过答案了 }cout<



