标签:正数 多少 get front 现在 超过 set second coder
这两天有新型病毒,吓得人都不敢出去,不过这也给我提供了更多刷题时间。
先来讲比赛吧,这场比赛算是比较水,也成为了第二个被我AK的abc。
https://atcoder.jp/contests/abc153
首先前四题实在太水了,这里也不多讲了。
第五题是一个经典的背包问题,
可以选择把空间开大一点,就可以解决怪兽血量低于0的问题,不过我比赛时是枚举最后一击,再枚举此时怪兽的血量,最后取一下最小值,就搞定了。
代码:
1 #include<bits/stdc++.h> 2 #define ll long long 3 #define F first 4 #define S second 5 #define P pair 6 #define FOR(i,a,b) for(int i=a;i<=b;i++) 7 #define V vector 8 #define RE return 9 #define ALL(a) a.begin(),a.end() 10 #define MP make_pair 11 #define PB push_back 12 #define PF push_front 13 #define FILL(a,b) memset(a,b,sizeof(a)) 14 using namespace std; 15 int a[1005],b[1005],dp[10005]; 16 int main(){ 17 ios::sync_with_stdio(0); 18 cin.tie(0); 19 int m,n; 20 cin>>m>>n; 21 FOR(i,1,n)cin>>a[i]>>b[i]; 22 int ans=1e9; 23 FOR(i,1,m)dp[i]=ans; 24 FOR(i,1,n){ 25 for(int j=a[i];j<=m;j++)dp[j]=min(dp[j],dp[j-a[i]]+b[i]); 26 } 27 FOR(i,1,n){ 28 for(int j=m;j>=max(0,m-a[i]);j--){ 29 ans=min(ans,dp[j]+b[i]); 30 } 31 } 32 cout<<ans; 33 RE 0; 34 }
第六题就相对没这么简单了,是一道贪心题。
这里不难发现,每炸一个炸弹,就必须让区间的左端点为最左边的存活的怪兽的坐标。不过这里要处理一下,因为一颗炸弹可以炸到多个怪兽,要把后面怪兽的血量也减去a。
这可以用双指针,让每次的左端点对准一只最左边的怪兽。我们知道炸弹爆炸范围的右端点肯定是单调向右移动的,所以就直接找到第一个右端点到这只怪兽的炸弹,现在也知道现在已经用了多少个炸弹,这样就可以知道这个怪兽已经被多少炸弹炸到过了。这样就可以知道这个怪兽还需要炸多少次,再继续往下推下去,最终得出答案。
上代码:
1 #pragma GCC optimize(2) 2 #include<bits/stdc++.h> 3 #define ll long long 4 #define F first 5 #define S second 6 #define P pair 7 #define FOR(i,a,b) for(int i=a;i<=b;i++) 8 #define V vector 9 #define RE return 10 #define ALL(a) a.begin(),a.end() 11 #define MP make_pair 12 #define PB push_back 13 #define PF push_front 14 #define FILL(a,b) memset(a,b,sizeof(a)) 15 using namespace std; 16 int n; 17 V<int> v[200005]; 18 int fa[200005],de[200005];bool vis[200005]; 19 void dfs(int p,int d){ 20 de[p]=d; 21 for(int i=0;i<v[p].size();i++){ 22 if(v[p][i]!=fa[p]){ 23 fa[v[p][i]]=p; 24 dfs(v[p][i],d+1); 25 } 26 } 27 } 28 int get(int p){ 29 if(de[p]!=-1)return de[p]; 30 return de[p]=get(fa[p])+1; 31 } 32 int main(){ 33 scanf("%d",&n); 34 int x,y; 35 FOR(i,2,n)scanf("%d%d",&x,&y),v[x].PB(y),v[y].PB(x); 36 fa[1]=-1; 37 dfs(1,0); 38 int maxi=0,a1,a2,a3; 39 FOR(i,1,n){ 40 if(de[i]>maxi){ 41 maxi=de[i];a1=i; 42 } 43 } 44 fa[a1]=-1; 45 dfs(a1,0); 46 maxi=0;int ans=0; 47 FOR(i,1,n){ 48 if(de[i]>maxi){ 49 maxi=de[i];a2=i; 50 } 51 } 52 ans=maxi; 53 int s=a2; 54 FILL(de,-1); 55 while(s!=-1){ 56 vis[s]=1;de[s]=0; 57 s=fa[s]; 58 } 59 maxi=0; 60 FOR(i,1,n){ 61 if(de[i]==-1)get(i); 62 if(de[i]>=maxi&&i!=a1&&i!=a2){ 63 maxi=de[i];a3=i; 64 } 65 } 66 printf("%d\n%d %d %d",maxi+ans,a1,a2,a3); 67 RE 0; 68 }
还有一题是我昨天做的,这题让我WA了6次,所以写一遍题解纪念一下。
https://atcoder.jp/contests/abc135/tasks/abc135_e
这里可以使X,Y都等于它们的绝对值,都是正数处理起来会更简单,同时要让X的值更小,否则交换X和Y的值,最后输出时再处理一下。
这里(0,0)到(X,Y)的距离如果大于走的路程,那么肯定是走的时候浪费步数了。
这里在处理时可以先特判一下是不是可以一步走到,因为一步走到是个特例,这个算法处理不了一步走到。
同时总步数都是两两抵消,所以被浪费的步数肯定是双数。要找出最小的跳跃次数使得浪费的步数是双数,且步数不为1(前面已经特判过了,再为1就肯定错)。
先让Y浪费步数,一直到能浪费的步数不超过k。这时再让X把剩下的步数浪费完,但是这一步还要走一些距离,让Y去走。
现在简单了,让X,Y不停向目标前进,直到不能走为止。如果X,Y还不到目标,但是因为前面有处理,所以下一步到X,Y肯定是可以的。
最后输出结果,太复杂了。。。。
代码:
1 #include<bits/stdc++.h> 2 #define ll long long 3 #define F first 4 #define S second 5 #define P pair 6 #define FOR(i,a,b) for(int i=a;i<=b;i++) 7 #define V vector 8 #define RE return 9 #define ALL(a) a.begin(),a.end() 10 #define MP make_pair 11 #define PB push_back 12 #define PF push_front 13 #define FILL(a,b) memset(a,b,sizeof(a)) 14 using namespace std; 15 int ni,nj; 16 V<P<int,int> > ans; 17 bool anf; 18 int main(){ 19 ios::sync_with_stdio(0); 20 cin.tie(0); 21 int x,y,k; 22 cin>>k>>x>>y; 23 int f1,f2; 24 if(x<0)f1=-1;else f1=1; 25 if(y<0)f2=-1;else f2=1; 26 if(abs(x)>abs(y))swap(x,y),anf=1; 27 x=abs(x);y=abs(y); 28 if(x+y==k){ 29 if(anf)swap(x,y); 30 cout<<"1\n"<<x*f1<<‘ ‘<<y*f2<<‘\n‘;RE 0; 31 } 32 int t=x+y; 33 if((t&1)&&!(k&1)){ 34 cout<<-1;RE 0; 35 } 36 int s=t/k+(t%k!=0); 37 s*=k; 38 while((s-t)&1||s/k<=1)s+=k; 39 int d=(s-t)>>1; 40 while(d>=k){ 41 nj-=k;d-=k;ans.PB(MP(ni,nj)); 42 } 43 ni-=d;nj+=k-d;ans.PB(MP(ni,nj)); 44 while(ni+k<=x){ 45 ni+=k;ans.PB(MP(ni,nj)); 46 } 47 while(nj+k<=y){ 48 nj+=k;ans.PB(MP(ni,nj)); 49 } 50 if(ni!=x||nj!=y){ 51 ans.PB(MP(x,y)); 52 } 53 cout<<ans.size()<<‘\n‘; 54 for(int i=0;i<ans.size();i++){ 55 if(anf)swap(ans[i].F,ans[i].S); 56 cout<<ans[i].F*f1<<‘ ‘<<ans[i].S*f2<<‘\n‘; 57 } 58 RE 0; 59 }
标签:正数 多少 get front 现在 超过 set second coder
原文地址:https://www.cnblogs.com/njwsf/p/12235531.html