首页 > 其他分享 >ABC369

ABC369

时间:2024-09-05 17:37:17浏览次数:8  
标签:10 const int LL long ABC369 path

 

C

对于一个等差数列,它里面包含的等差数列(取这个数列的第i位~第j位),必定也是等差数列。

寻找等差数列的时候,如果一个等差数列,向最左/最右加1个数后,仍是等差数列,则把它们加上。从而寻找所有场上的等差数列,必定是不重叠的,等差数列彼此独立。

从而可以从1遍历到n,O(n)复杂度。

对于每一段等差数列,只统计里面包含的长度大于等于2的等差数列。最后再加上长度等于1的等差数列,即为单独的每个数,为n。这样,思路会清晰一点

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define LL long long
 4 #define ULL unsigned long long
 5 
 6 const LL mod_1=1e9+7;
 7 const LL mod_2=998244353;
 8 
 9 const double eps_1=1e-5;
10 const double eps_2=1e-10;
11 
12 const int maxn=2e5+10;
13 
14 LL a[maxn];
15 
16 int main()
17 {
18     LL n,i,j,d;
19     LL sum=0;
20     cin>>n;
21     for (i=1;i<=n;i++)
22         cin>>a[i];
23     j=1;
24     for (i=1;i<n;)
25     {
26         d=a[i+1]-a[i];
27         j=i;
28         i++;
29         while (i<n && a[i+1]-a[i]==d)
30             i++;
31         sum+=1LL*(i-j)*(i-j+1)/2;
32     }
33     cout<<sum+n;
34 
35     return 0;
36 }

 

 

D

DP

写成数组形式,好理解一点,写少一点代码

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define LL long long
 4 #define ULL unsigned long long
 5 
 6 const LL mod_1=1e9+7;
 7 const LL mod_2=998244353;
 8 
 9 const double eps_1=1e-5;
10 const double eps_2=1e-10;
11 
12 const int maxn=2e5+10;
13 
14 LL f[maxn][2];
15 
16 
17 int main()
18 {
19     LL n,i,a;
20     f[0][0] = 0;
21     f[0][1] = -1e18;
22     cin>>n;
23     for (i=1;i<=n;i++)
24     {
25         cin>>a;
26         f[i][0] = max(f[i-1][0], f[i-1][1] + a*2);
27         f[i][1] = max(f[i-1][1], f[i-1][0] + a);
28     }
29     
30     cout<<max(f[n][0],f[n][1]);
31     return 0;
32 }

 

E

floyd 求两两每个点之间的距离 + dfs获得几个桥所有可能的顺序

看到别人有用next_permutation,而且是挺多人用这个,挺不错。

但是后面,直接一行写出情况,对于大部分人来说是不是容易写错?而且关键是挺多人都这样写,我感觉比较神奇emmm。我个人,感觉用dfs相对不容易写错。

dfs获得几个桥所有可能的顺序,其实就很像旅行商问题,所有城市都访问一遍。然后这里是桥可以选择两个方向,也不好用状态压缩。

g个点,2^g个方向,桥的顺序,g!排列组合,每种桥方向类型,g个权值和相加,O(2^g*g!*g) 19,200 再乘个Q,没问题

 

 

我在比赛的时候,把floyd的顺序搞反了,然后几天找不到问题,真的绷不住了!!!floyd算法,三重循环的顺序问题,不要写错了 - congmingyige - 博客园 (cnblogs.com)

 

 

 1 /*
 2 n,m的大小,对应创建数组的大小,不要弄混,特别是这类题,n<=400,m<=2e5,提交前要检查一遍。当RE的时候,就要第一时间意识到数组大小设置错误的问题
 3 
 4 怎么也调不出问题,包括检查代码,造样例,看题面,就立刻先切换到下一题。没必要花那么多时间耗在上面,否则检查错误,采用错误的方法,做很多无用功。而且影响做题时间和效率。这些时间,今早做下一题,有可能就做出来其它题了
 5 做选择,要么全攻下一题(意识到难发现错误在哪,立刻切换,检查时间不要太长),要么剩下这些时间,全力检查这一题,不要既这又那
 6 用assert等方式找一下问题所在,还有造一下大样例
 7 */
 8 #include <bits/stdc++.h>
 9 using namespace std;
10 #define LL long long
11 #define ULL unsigned long long
12 
13 const LL mod_1=1e9+7;
14 const LL mod_2=998244353;
15 
16 const double eps_1=1e-5;
17 const double eps_2=1e-10;
18 
19 const int maxn=4e2+10;
20 const int maxm=2e5+10;
21 
22 LL u[maxm],v[maxm],t[maxm],dist[maxn][maxn],b[10],g,n,result;
23 bool vis[10];
24 
25 void dfs(LL d, LL ans, LL road)
26 {
27     LL i,j;
28     if (ans==g)
29     {
30         result = min(result, road+dist[d][n]);
31         return;
32     }
33     for (i=1;i<=g;i++)
34         if (vis[i]==0)
35         {
36             j=b[i];
37 
38             vis[i]=1;
39             dfs(v[j], ans+1, road+dist[d][u[j]] + t[j]);
40             vis[i]=0;
41 
42             vis[i]=1;
43             dfs(u[j], ans+1, road+dist[d][v[j]] + t[j]);
44             vis[i]=0;
45         }
46 }
47 
48 int main()
49 {
50     LL m,q,i,j,k;
51     cin>>n>>m;
52     for (i=1;i<=n;i++)
53         for (j=1;j<=n;j++)
54             dist[i][j] = 1e15;
55     for (i=1;i<=n;i++)
56         dist[i][i]=0;
57     for (i=1;i<=m;i++)
58     {
59         cin>>u[i]>>v[i]>>t[i];
60         dist[ u[i] ][ v[i] ] = dist[ v[i] ][ u[i] ] = min(dist[ u[i] ][ v[i] ], t[i]);
61     }
62     
63     for (k=1;k<=n;k++)
64         for (i=1;i<=n;i++)
65             for (j=1;j<=n;j++)
66                  dist[i][j] = min(dist[i][j], dist[i][k]+dist[k][j]);
67     /*
68     for (i=1;i<=n;i++)
69         for (j=1;j<=n;j++)
70             assert(dist[i][j]<1e15);
71     */
72 
73     cin>>q;
74     while (q--)
75     {
76         cin>>g;
77         for (i=1;i<=g;i++)
78             cin>>b[i];
79         memset(vis,0,sizeof(vis));
80         result=1e18;
81         dfs(1,0,0);
82         //assert(result<1e18);
83         cout<<result<<endl;
84     }
85 
86     return 0;
87 }
88 /*
89 g个点
90 2^g个方向,桥的顺序,g!排列组合,每种桥方向类型,g个权值和相加,O(2^g*g!*g) 19,200 再乘个Q,没问题
91 */

 

F

应该看一下题面,在剩余1个小时的时候,这样才有时间做和取舍(题D、E) 这种属于题面很容易理解,也很容易想到解法的。就是写的过程中容易写错,debug也是,需要时间长一点 感觉这是高手和某类菜鸟的区别。某类菜鸟也可以很快找到解法,就是写代码和调试代码的时候,对于这类比较琐碎的代码,需要写挺久

 

能想到的基础题目是用DP做,二维方格,dp[i][j]=max(dp[i-1][j], dp[i][j-1])。

现在是n、m相乘比较大,然后硬币数比较少。

因为只能向下或者向右,所以对于一个点,只有列的数值小于等于它的点,才能访问到它。这容易想到树状数组。同样,对于行,也是只有行的数值小于等于它的点,才能访问到它。

f[i]= max(f[j]) + 1。 i表示这个点的列数值为i,j是所有小于i的数,用树状数组获取f数组里1~i的最大值。

按照硬币行数值优先,然后列数值优先的顺序排序,然后依次访问硬币。可以确保,对于该硬币,前面的硬币的行都是小于等于它,后面的硬币的行都是大于它,或者行等于它但是列大于它,无法从后面的硬币到该硬币。

 

  1 /*
  2 应该看一下题面,在剩余1个小时的时候,这样才有时间做和取舍(题D、E)
  3 这种属于题面很容易理解,也很容易想到解法的。就是写的过程中容易写错,debug也是,需要时间长一点
  4 感觉这是高手和某类菜鸟的区别。某类菜鸟也可以很快找到解法,就是写代码和调试代码的时候,对于这类比较琐碎的代码,需要写挺久
  5 
  6 用xpre,ypre,x,y,这样变量不容易搞错。还有,找问题的,多检查一下变量,这种变量最容易写错
  7 */
  8 #include <bits/stdc++.h>
  9 using namespace std;
 10 #define LL long long
 11 #define ULL unsigned long long
 12 
 13 const LL mod_1=1e9+7;
 14 const LL mod_2=998244353;
 15 
 16 const double eps_1=1e-5;
 17 const double eps_2=1e-10;
 18 
 19 const int maxn=2e5+10;
 20 
 21 pair<int,int> par[maxn];
 22 
 23 map<pair<int,int>, pair<int,int> > mp;
 24 
 25 pair<int, int> pre[maxn];
 26 int f[maxn];
 27 vector<string> vec;
 28 
 29 void add_path(pair<int,int> dpre, pair<int,int> d)
 30 {
 31     int i,j;
 32     string str="";
 33     for (i=dpre.first;i<d.first;i++)
 34         str+='D';
 35     for (j=dpre.second;j<d.second;j++)
 36         str+='R';
 37     vec.push_back(str);
 38 }
 39 
 40 void dfs(pair<int,int> d)
 41 {
 42     pair<int,int> dpre;
 43 
 44     dpre = mp[d];
 45 
 46     if (dpre!=make_pair(-1,-1))
 47     {
 48         add_path(dpre,d);
 49         dfs(dpre);
 50     }
 51     else
 52         add_path(make_pair(1,1),d);
 53 }
 54 
 55 int main()
 56 {
 57     int h,w,n,x,y,v,i,j,y_max=2e5;
 58     pair<int,int> dpre,d;
 59     cin>>h>>w>>n;
 60     memset(f,0,sizeof(f));
 61     for (i=0;i<n;i++)
 62     {
 63         cin>>x>>y;
 64         par[i] = make_pair(x,y);
 65     }
 66     sort(par, par+n);
 67 
 68     for (j=0;j<n;j++)
 69     {
 70         x = par[j].first;
 71         y = par[j].second;
 72         dpre = make_pair(-1,-1);
 73 
 74         v = 0;
 75         for (i=y;i>=1;i-=i&-i)
 76             if (f[i]>v)
 77             {
 78                 v=f[i];
 79                 dpre = pre[i];
 80             }
 81 
 82         v++;
 83 
 84         if (v>f[y])
 85         {
 86             d = make_pair(x,y);
 87             mp[d] = dpre;
 88 
 89             for (i=y;i<=y_max;i+=i&-i)
 90                 if (v>f[i])
 91                 {
 92                     f[i]=v;
 93                     pre[i]=d;
 94                 }
 95         }
 96     }
 97     
 98     v=0;
 99     for (i=y_max;i>=1;i-=i&-i)
100         if (f[i]>v)
101         {
102             v=f[i];
103             dpre=pre[i];
104         }
105     cout<<v<<endl;
106     add_path(dpre,make_pair(h,w));
107     dfs(dpre);
108     reverse(vec.begin(), vec.end());
109     for (auto d:vec)
110         cout<<d;
111 
112     return 0;
113 }

 

学习官方代码,

 

vector 初始化,第二个数,就是vector里初始化的数值

 

LIS,二分的写法,4行就搞定了??!!!

对于pre数组,记录点id,而不是记录二维坐标,这样方便一点,写少一点代码

用二分的写法,而不是树状数组的写法,只用修改一次pre,这个点的pre就是数组里上一个点,用树状数组,每次+lowbit后,都要判断修改一次,总感觉代码量相对比较大,不利索

pre[i] = (it ? id[it - 1] : -1); 这个写法不错
 

官方也是用while、vector记录从终点出发,不断pre的点序列,然后用reverse,的确,这个好用。我感觉用dfs,写得挺不舒服的

1     int now = id[m];
2     while (now != -1) {
3         path.push_back(coins[now]);
4         now = pre[now];
5     }
6     path.emplace_back(1, 1);
7     reverse(path.begin(), path.end());

 

 

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 int main() {
 6     int h, w, n;
 7     cin >> h >> w >> n;
 8     vector<pair<int, int>> coins;
 9     for (int i = 0; i < n; i++) {
10         int r, c;
11         cin >> r >> c;
12         coins.emplace_back(r, c);
13     }
14     sort(coins.begin(), coins.end());
15     vector<int> dp(n, 1e9), id(n, -1), pre(n);
16     for (int i = 0; i < n; i++) {
17         int it = upper_bound(dp.begin(), dp.end(), coins[i].second) - dp.begin();
18         dp[it] = coins[i].second;
19         id[it] = i;
20         pre[i] = (it ? id[it - 1] : -1);
21     }
22     int m = n - 1;
23     while (id[m] == -1) --m;
24     vector<pair<int, int>> path = {{h, w}};
25     int now = id[m];
26     while (now != -1) {
27         path.push_back(coins[now]);
28         now = pre[now];
29     }
30     path.emplace_back(1, 1);
31     reverse(path.begin(), path.end());
32     string s;
33     for (int i = 0; i < (int) path.size() - 1; i++) {
34         int d = path[i + 1].first - path[i].first;
35         int r = path[i + 1].second - path[i].second;
36         while (d--) s.push_back('D');
37         while (r--) s.push_back('R');
38     }
39     cout << m + 1 << '\n' << s << '\n';
40 }

 

G

可以用,DP,f[i][j]。对于以i为根的子树,现在已经选取了j个点,但是这么多子树,j这么大,DP会超时的。

记录点1到某个点的长度,从大到小排序依次取

取了一个点后,点1到这个点经过的边,所有的边值都要变为0,即点1到其它点经过的边中,再用到这些边,也无法增加权值。

 

标签:10,const,int,LL,long,ABC369,path
From: https://www.cnblogs.com/cmyg/p/18398916

相关文章

  • [ABC369G] As far as possible
    考虑删除树上一条边\((u,v,l)\),此时剩余部分构成两个连通块,如果不包含节点\(1\)的连通块中有Aoki选择的点,那个这条边的贡献至少为\(2l\)。简单构造发现,当Takahashi构造的路径恰好为Aoki选择的点和\(1\)构成的虚树时,能够取到路径长度的最小值。此时我们将题目转......
  • 8.31 晚上 ABC369 总结 & 题解
    打了一天的比赛。ABCD太水了,直接放代码链接得了,点字母就能看对应代码。E-SightseeingTour看范围$N$只有$400$,所以我们可以先用floyd搞出任意两点间的距离。对于每次询问,发现$K_i$只有$5$,所以可以直接深搜应该走哪座桥,和应该走到哪一端。时间复杂度$O(N3+QK_i......
  • ABC369F F - Gather Coins 题解
    题目链接:https://atcoder.jp/contests/abc369/tasks/abc369_f题目大意:在一个\(H\timesW\)的二维迷宫中有\(N\)枚硬币,其中第\(i\)枚硬币在\((R_i,C_i)\)(本题中,我们用\((r,c)\)表示二维迷宫中从上到下第\(r\)行从左到右第\(c\)列的那个格子)。你一开始在迷宫的左......
  • abc369 题解
    切了A~F,还挺开心(但是如果上一次把G切了的话,我就上青了QAQ比赛链接:https://atcoder.jp/contests/abc369A-369题意:给定正整数\(a,b\)(\(1\lea,b\le100\)),请问有多少个整数\(x\)满足\(a,b,x\)排序后构成等差数列。思路:观察到\(a,b\)范围很小,直接枚举\(x\)即可。......
  • ABC369
    Alink判断\(A\),\(B\)之间可不可以放一个数,如果可以就是\(3\)个,不行就是\(2\)个(左右),但是如果\(A\),\(B\)相等就只有一个。点击查看代码#include<bits/stdc++.h>usingnamespacestd;signedmain(){ inta,b; cin>>a>>b; intx=b-a; if(x!=0){ if(x%2==0......