日常做题 和 abc153

Posted njwsf

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了日常做题 和 abc153相关的知识,希望对你有一定的参考价值。

这两天有新型病毒,吓得人都不敢出去,不过这也给我提供了更多刷题时间。

 

先来讲比赛吧,这场比赛算是比较水,也成为了第二个被我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 }
View Code

 

 

第六题就相对没这么简单了,是一道贪心题。

这里不难发现,每炸一个炸弹,就必须让区间的左端点为最左边的存活的怪兽的坐标。不过这里要处理一下,因为一颗炸弹可以炸到多个怪兽,要把后面怪兽的血量也减去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
%d %d %d",maxi+ans,a1,a2,a3);
67     RE 0;
68 } 
View Code

 

还有一题是我昨天做的,这题让我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
"<<x*f1<< <<y*f2<<
;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()<<
;
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<<
;
57     }
58     RE 0;
59 }
View Code

 

以上是关于日常做题 和 abc153的主要内容,如果未能解决你的问题,请参考以下文章

译文:18个实用的JavaScript代码片段,助你快速处理日常编程任务

日常写程序规范

[linux][c/c++]代码片段01

攻防世界 Reverse高手进阶区 2分题 easyre-153

攻防世界 Reverse高手进阶区 2分题 easyre-153

攻防世界 Reverse高手进阶区 2分题 easyre-153