考场:把问题抽象成n个点的有向完全图上找到一条边权和不超过t的最长链。再加上把题意理解错了,完全爆炸,GG
正解,观察到最优状态下跳跃一定是时高度是连续递增或递减的(我是sb),拍完序后正反两边dp就可以了。
连这种水题都拿不到分,noip怎么混???!!!
#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<algorithm> #include<cstring> #define N 55 using namespace std; int n,t,ans,dp[N][N]; struct zzh{ int c,h; }a[N]; bool cmp(zzh a,zzh b){ return a.h<b.h; } int main(){ freopen("meet.in","r",stdin); freopen("meet.out","w",stdout); scanf("%d",&n); for(int i=1;i<=n;++i)scanf("%d",&a[i].c); for(int i=1;i<=n;++i)scanf("%d",&a[i].h); scanf("%d",&t); sort(a+1,a+n+1,cmp);ans=1; memset(dp,0x3f,sizeof(dp));for(int i=1;i<=n;++i)dp[i][1]=a[i].c; for(int i=2;i<=n;++i) for(int j=2;j<=i;++j){ for(int k=1;k<i;++k) dp[i][j]=min(dp[k][j-1]+a[i].c+a[i].h-a[k].h,dp[i][j]); if(dp[i][j]<=t)ans=max(ans,j); } memset(dp,0x3f,sizeof(dp));for(int i=1;i<=n;++i)dp[i][1]=a[i].c; for(int i=n-1;i>=1;--i) for(int j=1;j<=n-i+1;++j){ for(int k=i+1;k<=n;++k) dp[i][j]=min(dp[k][j-1]+a[i].c+a[k].h-a[i].h,dp[i][j]); if(dp[i][j]<=t)ans=max(ans,j); } cout<<ans; fclose(stdin); fclose(stdout); return 0; }
这题挺好玩的。
考场:观察到第一项为a[1]+a[2],第二项为a[1]+a[3]但后面无法确定&*%¥#¥%懒得往后想了,直接枚举第一个数,把后面暴力算出来,水了60.
正解,直接枚举a[2]+a[3]是几,可以把枚举范围缩小很多,加上剪枝可过。
我常数太大过不了,强行把我枚举范围缩到20过了。
#include<iostream> #include<cstdio> #include<set> #include<algorithm> #include<map> #include<vector> #define N 302 using namespace std; int n,m,a[N*N],num[N],flag,tot,pre; map<int,int>mp; set<int>se; vector<int>vec[N]; int main(){ freopen("city.in","r",stdin); freopen("city.out","w",stdout); scanf("%d",&n);m=n*(n-1)/2; for(int i=1;i<=m;++i)scanf("%d",&a[i]); sort(a+1,a+m+1); for(int i=3;i<=20;++i) if((a[1]+a[2]-a[i])%2==0){ num[1]=(a[1]+a[2]-a[i])/2; if(num[1]==pre)continue;pre=num[1]; num[2]=a[1]-num[1];flag=0; for(int j=2;j<=m;++j){ if(se.find(a[j])==se.end())se.insert(a[j]); else mp[a[j]]++; } for(int j=3;j<=n;++j){ num[j]=*se.begin()-num[1]; if(mp[num[j]+num[1]])mp[num[j]+num[1]]--; else se.erase(se.begin()); for(int k=2;k<j;++k) if(se.find(num[k]+num[j])==se.end()){flag=1;break;} else { if(mp[num[j]+num[k]])mp[num[j]+num[k]]--; else se.erase(num[j]+num[k]); } if(flag)break; } if(!flag){ tot++; for(int j=1;j<=n;++j)vec[j].push_back(num[j]); } while(se.size())se.erase(se.begin()); mp.clear(); } printf("%d\n",tot); for(int i=0;i<tot;++i){ for(int j=1;j<=n;++j) printf("%d ",vec[j][i]); printf("\n"); } fclose(stdin); fclose(stdout); return 0; }
T3板子
#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #define N 100002 using namespace std; int n,m,kuai[318][10002],a[N],f[318][103][103],mx,n1,be[N],n2,l,r,p,v,ans,ji[318][10002]; inline int rd(){ int x=0;bool f=0; char c=getchar(); while(!isdigit(c)){ if(c=='-')f=1; c=getchar(); } while(isdigit(c)){ x=(x<<1)+(x<<3)+(c^48); c=getchar(); } return f?-x:x; } int main(){ freopen("light.in","r",stdin); freopen("light.out","w",stdout); n=rd();m=rd(); for(int i=1;i<=n;++i)a[i]=rd(),mx=max(mx,a[i]); n1=sqrt(n); for(int i=1;i<=n;++i){ be[i]=(i-1)/n1+1; kuai[be[i]][a[i]]++; } for(int i=1;i<=be[n];++i) for(int j=0;j<=mx;++j) ji[i][j]=kuai[i][j]+ji[i-1][j]; n2=sqrt(mx); for(int i=1;i<=be[n];++i) for(int j=1;j<=n2;++j) for(int k=(i-1)*n1+1;k<=min(n,i*n1);++k) f[i][j][a[k]%j]++; while(m--){ l=rd();r=rd();p=rd();v=rd(); ans=0; if(v>p){ printf("0\n"); continue; } if(p>mx){ if(v>mx){ printf("0\n"); continue; } if(be[l]==be[r]){ for(int i=l;i<=r;++i)if(a[i]==v)ans++; } else{ for(int i=l;i<=min(be[l]*n1,n);++i)if(a[i]==v)ans++; for(int i=(be[r]-1)*n1+1;i<=r;++i)if(a[i]==v)ans++; for(int i=be[l]+1;i<be[r];++i)ans+=kuai[i][v]; } printf("%d\n",ans); } else{ if(be[l]==be[r]){ for(int i=l;i<=r;++i)if(a[i]%p==v)ans++; } else{ for(int i=l;i<=min(n,be[l]*n1);++i)if(a[i]%p==v)ans++; for(int i=(be[r]-1)*n1+1;i<=r;++i)if(a[i]%p==v)ans++; if(p<=n2) for(int i=be[l]+1;i<be[r];++i)ans+=f[i][p][v]; else if(be[r]-1>be[l])for(int j=v;j<=mx;j+=p)ans+=ji[be[r]-1][j]-ji[be[l]][j]; } printf("%d\n",ans); } } fclose(stdin); fclose(stdout); return 0; }
正反两边KMP,大水题
#include<iostream> #include<cstdio> #include<cstring> #define N 100002 using namespace std; int n,n1,n2,nex[N],nex2[N],j,tag,tag2; char s[N],s1[N],s2[N],ss[N<<2]; inline void rd(){ scanf("%s",ss+1); int ti=strlen(ss+1),i; for(i=1;ss[i]!=',';++i)s[++n]=ss[i]; for(i=i+1;ss[i]!=',';++i)s1[++n1]=ss[i]; for(i=i+1;i<=ti;++i)s2[++n2]=ss[i]; } int main(){ freopen("dis.in","r",stdin); freopen("dis.out","w",stdout); rd(); for(int i=2;i<=n1;++i){ while(j&&s1[i]!=s1[j+1])j=nex[j]; if(s1[i]==s1[j+1])j++; nex[i]=j; } for(int i=1;i<=n2/2;++i)swap(s2[i],s2[n2-i+1]); j=0; for(int i=2;i<=n2;++i){ while(j&&s2[i]!=s2[j+1])j=nex2[j]; if(s2[i]==s2[j+1])j++; nex2[i]=j; } j=0; tag=tag2=0x3f3f3f3f; for(int i=1;i<=n;++i){ while(j&&s[i]!=s1[j+1])j=nex[j]; if(s[i]==s1[j+1])j++; if(j==n1){ tag=i; break; } } for(int i=1;i<=n/2;++i)swap(s[i],s[n-i+1]); j=0; for(int i=1;i<=n;++i){ while(j&&s[i]!=s2[j+1])j=nex2[j]; if(s[i]==s2[j+1])j++; if(j==n2){ tag2=i; break; } } int ans=n-tag2-tag; if(ans<0)printf("-1"); else printf("%d\n",ans); fclose(stdin); fclose(stdout); return 0; }
去重不加eps挂成10分,为啥不用sort去重!!!!
are you silly B??!!!
#include<iostream> #include<cstdio> #include<map> #include<cmath> #include<algorithm> #define N 1002 #define mm make_pair using namespace std; int xf,xs,yf,ys,r,n,ans,tot,top; double ling[N]; bool tag[N]; const double eps=1e-7; struct sb{ double x,y; }ji[N]; struct zzh{ double k,b; }a[N]; bool cmp(sb a,sb b){ if(fabs(a.x-b.x)>eps)return a.x<b.x; else return a.y<b.y; } int main(){ freopen("cake.in","r",stdin); freopen("cake.out","w",stdout); scanf("%d%d",&r,&n);ans=1; for(int i=1;i<=n;++i){ scanf("%d%d%d%d",&xf,&yf,&xs,&ys);top=0; if(xs==xf){ ling[++tot]=xs;tag[i]=1; for(int j=1;j<i;++j)if(!tag[j]){ double x=xs,y=xs*a[j].k+a[j].b; if(x*x+y*y<=r*r)ji[++top].x=x,ji[top].y=y; } sort(ji+1,ji+top+1,cmp); for(int i=1;i<=top;++i)if(fabs(ji[i].x-ji[i-1].x)>eps||fabs(ji[i].y-ji[i].y)>eps)ans++; } else{ a[i].k=(double)(ys-yf)/(double)(xs-xf);a[i].b=(double)ys-a[i].k*xs; for(int j=1;j<i;++j)if(!tag[j]){ double x=(a[j].b-a[i].b)/(a[i].k-a[j].k); double y=x*a[i].k+a[i].b; if(x*x+y*y<=r*r)ji[++top].x=x,ji[top].y=y; } for(int j=1;j<=tot;++j){ double y=ling[j]*a[i].k+a[i].b,x=ling[j]; if(x*x+y*y<=r*r)ji[++top].x=x,ji[top].y=y; } sort(ji+1,ji+top+1,cmp); for(int i=1;i<=top;++i)if(fabs(ji[i].x-ji[i-1].x)>eps||fabs(ji[i].y-ji[i].y)>eps)ans++; } ans++; } printf("%d\n",ans); fclose(stdin); fclose(stdout); return 0; }
垃圾丧病卡读入
#include<iostream> #include<cstdio> #include<cstring> #define N 1000002 using namespace std; int n,k,a,b,head[N],tot,ta1[N],ta2[N],co[N],num[N],ans,st[N],top,h[N],now[N]; bool vis[N]; struct zzh{ int n,to; }e[N<<1]; inline void add(int u,int v){ e[++tot].n=head[u]; e[tot].to=v; head[u]=tot; } void dfs(){ st[top=1]=1;memset(ta2,-0x3f,sizeof(ta2)); for(int i=1;i<=n;++i)h[i]=head[i]; while(top){ int u=st[top],i;vis[u]=1; if(now[u]){ int v=now[u]; if(co[v]==1)ta1[u]=max(ta1[u],num[v]+1);//这里计算如果是未覆盖的情况,不算当前节点有多少未覆盖 else ta2[u]=max(ta2[u],num[v]-1); now[u]=0; } for(i=h[u];i;i=e[i].n)if(!vis[e[i].to]){ int v=e[i].to; st[++top]=v;h[u]=e[i].n;now[u]=v;break; } if(!i){ if(ta2[u]>=ta1[u]){//如果儿子都能覆盖 co[u]=2,num[u]=ta2[u]; if(num[u]<0)co[u]=1,num[u]=0; } else { co[u]=1;num[u]=ta1[u]; if(num[u]==k)co[u]=2,num[u]=k,ans++; } --top; } } } inline int rd(){ int x=0;char c=getchar(); while(!isdigit(c))c=getchar(); while(isdigit(c)){ x=(x<<1)+(x<<3)+(c^48); c=getchar(); } return x; } int main(){ freopen("coffee.in","r",stdin); freopen("coffee.out","w",stdout); n=rd();k=rd(); for(int i=1;i<n;++i)a=rd(),b=rd(),add(a,b),add(b,a); dfs(); if(co[1]==1)ans++; cout<<ans; fclose(stdin); fclose(stdout); return 0; }