atcoder beginner 346 C F G 题解
看到别人的视频讲解 AtCoder Beginner Contest 346 A 至 G 題讲解 by dreamoon
C
如果用sort写,那么再从小到大遍历也需要写几行
#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <cstdbool> #include <string> #include <algorithm> #include <iostream> #include <sstream> #include <ctime> #include <stack> #include <vector> #include <queue> #include <set> #include <map> using namespace std; #define ll long long #define ull unsigned long long const ll mod_1=1e9+7; const ll mod_2=998244353; const double eps_1=1e-5; const double eps_2=1e-10; const int maxn=2e5+10; int a[maxn]; int main() { int n,i,k; ll sum=0; scanf("%d%d",&n,&k); for (i=1;i<=n;i++) { scanf("%d",&a[i]); } sort(a+1,a+n+1); sum=1ll*k*(k+1)/2; a[0]=0; for (i=1;i<=n;i++) if (a[i]<=k && a[i]!=a[i-1]) sum-=a[i]; printf("%lld",sum); return 0; }
map也是同样的情况,是否出现过,map_1.find()!=map_1.end()
set的写法
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <cmath> 5 #include <cstdbool> 6 #include <string> 7 #include <algorithm> 8 #include <iostream> 9 #include <sstream> 10 #include <ctime> 11 #include <stack> 12 #include <vector> 13 #include <queue> 14 #include <set> 15 #include <map> 16 using namespace std; 17 #define ll long long 18 #define ull unsigned long long 19 20 const ll mod_1=1e9+7; 21 const ll mod_2=998244353; 22 23 const double eps_1=1e-5; 24 const double eps_2=1e-10; 25 26 const int maxn=2e5+10; 27 28 set<int> set_1; 29 30 int main() 31 { 32 int n,k,i,a; 33 ll sum; 34 scanf("%d%d",&n,&k); 35 sum=k*(k+1ll)/2; 36 for (i=1;i<=n;i++) 37 { 38 scanf("%d",&a); 39 if (a<=k) 40 sum -= set_1.insert(a).second * a; 41 } 42 printf("%lld",sum); 43 44 45 return 0; 46 }
F
一个比较明显的,从这个字符a开始,后面k个字符b后的的位置(dp) + 二分。
预估场上的时间,还是有些细节容易写错,当最后剩余时间不多的时候容易慌。
这样 1 前面A-E尽快做完,这样F容易安全渡过 2 F在剩余时间少的时候,大心脏的完成。都要培养
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <cmath> 5 #include <cstdbool> 6 #include <string> 7 #include <algorithm> 8 #include <iostream> 9 #include <sstream> 10 #include <ctime> 11 #include <stack> 12 #include <vector> 13 #include <queue> 14 #include <set> 15 #include <map> 16 using namespace std; 17 #define ll long long 18 #define ull unsigned long long 19 20 const ll mod_1=1e9+7; 21 const ll mod_2=998244353; 22 23 const double eps_1=1e-5; 24 const double eps_2=1e-10; 25 26 const int maxn=1e5+10; 27 28 29 30 char str1[maxn], str2[maxn]; 31 ll f[26][maxn], cnt[26], next_fit_pos[26][maxn], next_fit_index[26][maxn]; 32 ll s2[maxn]; 33 34 int main() 35 { 36 ll n,len1,len2,ch,i,j,k,o,pos_in_loop,cur_pos_index,xx,yy,max_length; 37 ll l,r,mid,cur_pos; 38 bool vis; 39 cin>>n; 40 scanf("%s%s",str1,str2); 41 len1=strlen(str1); 42 len2=strlen(str2); 43 max_length=len1*n; 44 memset(cnt,0,sizeof(cnt)); 45 //先加上试试 46 memset(next_fit_pos,0,sizeof(next_fit_pos)); 47 memset(next_fit_index,0,sizeof(next_fit_index)); 48 memset(f,0,sizeof(f)); 49 memset(s2,0,sizeof(s2)); 50 51 for (i=0;i<len1;i++) 52 { 53 ch = str1[i]-'a'; 54 f[ch][ cnt[ch]++ ]=i; 55 } 56 57 for (i=0;i<len2;i++) 58 s2[i] = str2[i]-'a'; 59 60 for (i=0;i<26;i++) 61 if (cnt[i]>0) 62 { 63 k=0; 64 for (j=0;j<len1;j++) 65 { 66 if (j==f[i][k]) 67 { 68 k++; 69 if (cnt[i]==k) 70 { 71 for (o=j;o<len1;o++) 72 { 73 next_fit_pos[i][o]=len1+f[i][0]-o; 74 next_fit_index[i][o]=0; 75 } 76 break; 77 } 78 } 79 next_fit_pos[i][j]=f[i][k]-j; 80 next_fit_index[i][j]=k; 81 } 82 } 83 84 //binary search 85 86 l=1,r=n*len1/len2; 87 88 while (l<=r) 89 { 90 mid = (l+r)/2; 91 92 //if ok 93 94 vis=1; 95 96 cur_pos=-1; 97 for (i=0;i<len2;i++) 98 { 99 ch=s2[i]; 100 101 if (cnt[ch]==0) 102 { 103 cout<<0; 104 return 0; 105 } 106 107 if (cur_pos==-1) 108 { 109 cur_pos=f[ch][0]; 110 cur_pos_index=0; 111 } 112 else 113 { 114 pos_in_loop=cur_pos%len1; 115 cur_pos += next_fit_pos[ch][pos_in_loop]; 116 cur_pos_index = next_fit_index[ch][pos_in_loop]; 117 } 118 119 xx=(mid-1)/cnt[ch]; 120 yy=(mid-1)%cnt[ch]; 121 122 yy+=cur_pos_index; 123 if (yy>=cnt[ch]) 124 { 125 xx++; 126 yy-=cnt[ch]; 127 } 128 129 cur_pos = cur_pos - f[ch][cur_pos_index] + xx * len1 + f[ch][yy]; 130 131 if (cur_pos>=max_length) 132 { 133 vis=0; 134 break; 135 } 136 } 137 138 if (!vis) 139 r=mid-1; 140 else 141 l=mid+1; 142 } 143 144 cout<<r; 145 146 return 0; 147 } 148 /* 149 3 150 aaa 151 aaa 152 153 3 154 aaa 155 a 156 157 3 158 aaaaa 159 aaaa 160 161 162 ============= 163 164 asd容易乱打 165 166 3 167 sadasdasdsdasdaasdas 168 asd 169 170 output 7 171 sadasdasdsdasdaasdassadasdasdsdasdaasdassadasdasdsdasdaasdas 172 173 ============= 174 175 176 177 178 179 180 */
G
题目转化为求二维线段树
二维线段树 - congmingyige - 博客园 (cnblogs.com) : 这种写法内存不太够用,a[maxn*4][maxn*4]
题目 CSES - Area of Rectangles ; 对应程序 CSES-Solutions/Additional Problems/Area of Rectangles.cpp at main · Jonathan-Uy/CSES-Solutions · GitHub
扫描线
扫描线 - OI Wiki (oi-wiki.org) 例题也是二维矩阵相交面积
如果要求修改区间[l,r] ,把所有包含在区间[l,r] 中的节点都遍历一次、修改一次,时间复杂度无法承受。我们这里要引入一个叫做 「懒惰标记」 的东西。
懒惰标记,简单来说,就是通过延迟对节点信息的更改,从而减少可能不必要的操作次数。每次执行修改时,我们通过打标记的方法表明该节点对应的区间在某一次操作中被更改,但不更新该节点的子节点的信息。实质性的修改则在下一次访问带有标记的节点时才进行。
===
没有求a[l]-a[r],所以不用lazy标记
加上文件头 #include <array>
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <cmath> 5 #include <cstdbool> 6 #include <string> 7 #include <algorithm> 8 #include <iostream> 9 #include <sstream> 10 #include <ctime> 11 #include <stack> 12 #include <vector> 13 #include <queue> 14 #include <set> 15 #include <map> 16 #include <array> 17 using namespace std; 18 #define LL long long 19 #define ULL unsigned long long 20 21 const LL mod_1=1e9+7; 22 const LL mod_2=998244353; 23 24 const double eps_1=1e-5; 25 const double eps_2=1e-10; 26 27 const int maxn=2e5+10; 28 const int maxm=maxn*4; 29 30 array<int,4> op[maxn*2]; 31 32 int a[maxn],nex[maxn],lef[maxn],righ[maxn]; 33 34 int leftmost_pos[maxn],rightmost_pos[maxn]; 35 36 int f[maxm],tag[maxm],siz[maxm]; 37 38 LL result=0; 39 40 void build(int index, int l, int r) 41 { 42 siz[index]=r-l+1; 43 if (l==r) 44 return; 45 int m=(l+r)>>1; 46 build(index<<1,l,m); 47 build(index<<1|1,m+1,r); 48 } 49 50 void modify(int index,int l, int r, int ll, int rr, int val) 51 { 52 if (ll<=l && r<=rr) 53 { 54 tag[index]+=val; 55 56 if (l==r) 57 f[index]= (tag[index]>0 ? 1:0); 58 else 59 f[index]= (tag[index]>0 ? siz[index]:f[index<<1]+f[index<<1|1]); 60 return; 61 } 62 int m=(l+r)>>1; 63 if (m>=ll) 64 modify(index<<1,l,m,ll,rr,val); 65 if (m+1<=rr) 66 modify(index<<1|1,m+1,r,ll,rr,val); 67 f[index]= (tag[index]>0 ? siz[index]:f[index<<1]+f[index<<1|1]); 68 } 69 70 int main() 71 { 72 int n,i,y_last=-1; 73 scanf("%d",&n); 74 for (i=1;i<=n;i++) 75 scanf("%d",&a[i]); 76 for (i=1;i<=n;i++) 77 { 78 leftmost_pos[i]=1; 79 rightmost_pos[i]=n; 80 } 81 for (i=1;i<=n;i++) 82 { 83 lef[i] = leftmost_pos[ a[i] ]; 84 leftmost_pos[ a[i] ] = i+1; 85 } 86 for (i=n;i>=1;i--) 87 { 88 righ[i] = rightmost_pos[ a[i] ]; 89 rightmost_pos[ a[i] ] = i-1; 90 } 91 92 for (i=1;i<=n;i++) 93 { 94 op[(i-1)<<1] = {i, 1, lef[i]+1, i+1}; ///这两个+1性质不同 95 op[(i-1)<<1|1] = {righ[i]+1, -1, lef[i]+1, i+1}; 96 } 97 98 sort(op, op+n*2); 99 memset(f,0,sizeof(f)); 100 memset(tag,0,sizeof(tag)); 101 102 int value_max=n+1; 103 build(1,1,value_max); 104 105 for (i=0;i<n*2;i++) 106 { 107 result+=(op[i][0]-y_last)*f[1]; 108 modify(1, 1, value_max, op[i][2], op[i][3], op[i][1]); 109 y_last=op[i][0]; 110 } 111 cout<<result; 112 113 return 0; 114 } 115 /* 116 1 117 1 118 119 2 120 1 2 121 122 3 123 1 2 3 124 125 4 126 1 2 3 4 127 */