最近也那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"<<endl;
return 0;
}
c_cur=c>>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]<c;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<<res;
return 0;
}
一眼dp,但是那个时候还没听y总的dp降维,二维dp的o(n^2)炸了
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]);
}
累加匹配的后缀,因为只能往队头移动
#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<<n-ans;
return 0;
}
两个思路:
①分层图最短路(注意有的题会卡spfa,我觉得用dijkstra稳妥点)
②dp+dijkstra
这里就说一下分层图的做法:分层图的核心我个人理解就是把原图平行k次,多添加了上一层到下一层的费用为0的边,然后和普通的最短路问题一样了
这里注意可能k次免费可能并没有用完
#include
#include
#include
#include
#include
#include
using namespace std;
typedef pair<int,int> 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<yz> 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<k;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<<min_val<<endl;
return 0;
}
签到题
#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<<ans<<endl;
return 0;
}
并查集的题,也比较划水,可以去做做洛谷上的食物链那题
#include
using 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<<endl;return 0;}//如果出现了i既是好人又是坏人的情况,则无解
}
for(int i=1;i<=n;i++){
ans+=max(sz[find(i)],sz[find(i+n)]);//统计答案 ,取max是因为贪心取最大就好,因为两个不同条件的成立带来的影响是不一样的
sz[find(i)]=sz[find(i+n)]=0;//注意清0,因为之前已经统计过答案了
}cout<<ans<<endl;
return 0;
}