Atcoder Beginner Contest 449
直接输出
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 #include <bits/stdc++.h> using namespace std;#define int long long const int maxn=100002 ;double n;double pi=3.141592653589793 ;signed main () { scanf ("%lf" ,&n); n/=2 ; printf ("%lf" ,pi*n*n); return 0 ; }
观察可知巧克力块永远保持矩形的形状,故只需要定义两个变量维护矩形的长宽即可。
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 #include <bits/stdc++.h> using namespace std;#define int long long const int maxn=1002 ;int h,w,q,op,tmp;int a[maxn][maxn];signed main () { cin>>h>>w; cin>>q; int nowx=h,nowy=w; while (q--) { cin>>op>>tmp; if (op==1 ) { cout<<tmp*nowy<<endl; nowx=nowx-tmp; } else { cout<<tmp*nowx<<endl; nowy=nowy-tmp; } } return 0 ; }
考虑滑动窗口,维护 这个区间内和
不同的字符的数量,该数量便是以 为右端点的答案数 。复杂度
。
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 #include <bits/stdc++.h> using namespace std;#define int long long const int maxn=100002 ;string s; int l,r,L,R,n,ans;int tong[30 ];signed main () { cin>>n>>l>>r; cin>>s; for (int j=l; j<=n-1 ;j++) { tong[s[j-l]-'a' ]++; if (j-r-1 >=0 ) { tong[s[j-r-1 ]-'a' ]--; } ans+=tong[s[j]-'a' ]; } cout<<ans; return 0 ; }
出的相当不错的一道题。首先暴力复杂度
不可行,考虑优化暴力,一个很显然的思路就是对每一列单独统计出有几个黑点。对于一个竖列上的所有点,我们发现其基本可以分成三部分: 。显然,对于第二个区间,点为黑/白取决于
的奇偶性;对于第一、三个区间,点为黑/白取决于
的奇偶性(等价地可以转换为这个区间内
为偶数的点的个数)。接下来的细节处理也很容易出错,我们考虑的这一列的区间为
,我们要求出其与上面三个区间的交集,然后统计答案。具体方法见代码。还有一个小tips,求区间中偶数个数的公式为:对于区间
,偶数的个数为 。
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 #include <bits/stdc++.h> using namespace std;#define int long long const int maxn=100002 ;int L,R,D,U,ans;int get_even (int l,int r) { if (l>r) return 0 ; if (l==r) return (l+1 )%2 ; return r/2 -(l-1 )/2 ; } signed main () { cin>>L>>R>>D>>U; for (int i=L;i<=R;i++) { int maxh=min (abs (i),U); int minh=max (-abs (i),D); if (abs (i)%2 ==0 &&(maxh>=minh)) ans+=(maxh-minh+1 ); int top_l=max (D, abs (i)+1 ); if (top_l<=U) ans+=get_even (top_l,U); int bot_r=min (U,-abs (i)-1 ); if (D<=bot_r) ans+=get_even (-bot_r,-D); } cout<<ans; return 0 ; }
略有些麻烦的题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 #include <bits/stdc++.h> using namespace std;#define int long long const int maxn=1000002 ;int n,m,q,x;int a[maxn],tong[maxn],qzh[maxn],num;int tree[maxn];struct nodd { int val,id; }sorttong[maxn]; struct nodd2 { int pos,num,id,ans; }res[maxn]; bool cmp (nodd x,nodd y) { if (x.val==y.val) return x.id<y.id;else return x.val<y.val;}bool cmp2 (nodd2 x,nodd2 y) { return x.pos<y.pos; }bool cmp3 (nodd2 x,nodd2 y) { return x.id<y.id; }void ins (int pos, int delta) { for (;pos<=m;pos+=pos&-pos) { tree[pos]+=delta; } } int get (int k) { int pos=0 ; for (int i=18 ;i>=0 ;i--) { if ((pos+(1 <<i)<=m)&&(tree[pos+(1 <<i)]<k)) { pos+=(1 <<i); k-=tree[pos]; } } return pos+1 ; } int Getnum (int val) { int pos=0 ,l=1 ,r=m; while (l<=r) { int mid=(l+r)/2 ; if (sorttong[mid].val<val) { l=mid+1 ; pos=mid; } else r=mid-1 ; } if (pos==0 ) return 0 ; else return val*pos-qzh[pos]; } int Getpos (int val) { int l=1 ,r=m,pos=m; while (l<=r) { int mid=(l+r)/2 ; if (sorttong[mid].val<=val) { l=mid+1 ; pos=mid; } else r=mid-1 ; } return pos; } signed main () { cin>>n>>m; for (int i=1 ;i<=n;i++) { cin>>a[i]; tong[a[i]]++; } for (int i=1 ;i<=m;i++) { sorttong[i].val=tong[i]; sorttong[i].id=i; } sort (sorttong+1 ,sorttong+1 +m,cmp); for (int i=1 ;i<=m;i++) qzh[i]=qzh[i-1 ]+sorttong[i].val; cin>>q; while (q--) { cin>>x; if (x<=n) { res[++num].ans=a[x]; res[num].id=num; res[num].pos=-1 ; continue ; } int l=1 ,r=2e13 ; int ansH=0 ; while (l<=r) { int mid=(l+r)/2 ; if (Getnum (mid)<(x-n)) { l=mid+1 ; ansH=mid; } else r=mid-1 ; } res[++num].num=x-n-Getnum (ansH); res[num].pos=min (ansH,n); res[num].id=num; } sort (res+1 ,res+1 +num,cmp2); int treesize=0 ; for (int i=1 ;i<=num;i++) { if (res[i].pos==-1 ) continue ; while (sorttong[treesize+1 ].val<=res[i].pos&&(treesize+1 )<=m) { treesize++; ins (sorttong[treesize].id,1 ); } res[i].ans=get (res[i].num); } sort (res+1 ,res+1 +num,cmp3); for (int i=1 ;i<=num;i++) cout<<res[i].ans<<endl; return 0 ; }
感觉其实比E简单?正难则反,考虑哪些点不能成为答案。我们发现一个黑点能够“污染”它左上角的一片区域,这片区域的长宽是题目要求的矩形的长宽。换言之,这个区域里的所有点都不可能成为答案(即不能成为题目要求矩形的左上角的点),所以我们对于所有的黑点求“污染区域”的面积之和即可。这便化为了一个经典的矩形面积并的问题。