トピックリンク
A. Vovaと鉄道
問題の意味:指定された区間[1、L]、区間[L、R]、V所与。[1、L]においてQ [L、R] V内に存在しないは、除数番号の数です。
溶液:第1の全区間除数V、マイナス[L、R]除数を見つけます。
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin>>n;
while(n--)
{
long long L,v,l,r,ans=0;
cin>>L>>v>>l>>r;
ans=L/v-r/v+(l-1)/v;
cout<<ans<<'\n';
}
return 0;
}
B.ヒーター
質問の意味:Vovaハウスは一次元座標系、N-部屋で、部屋に与えるために、ヒータを表す[POS-R + 1、POS + R-1〕暖房の範囲のために。rが与えられ、各ヒータについても同様です。Q.は、少なくともオープンヒーターを選択する方法、それはすべての部屋がに加熱することができることができます。
ソリューション:シンプルな欲プラス暴力。Iが加熱室を選択した場合、まず、範囲の隣の部屋が選択され、[I + 1、iがR * 2-1 +]。部屋の各々は、ヒータを有しているので、最適解は[I + 1つの部屋の次のセグメントを選択することであるように、周りを覆うことができる加熱範囲は、最良の選択は、重複しない二つの部分を加熱部屋の中央であります、私は、r * 2-1]前後に横断しました+。客室の第1の範囲を選択すると、[1、R]です。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2020;
int a[maxn];
int main()
{
int n,r;
cin>>n>>r;
for(int i=1;i<=n;i++) cin>>a[i];
int cur=0;//之前选择的房间位置
int i=r;//能够贪心选择最远房间的位置
int flag,ans=0;
while(1){
flag=1;
for(int j=i;j>cur&&flag;--j){
if(a[j]) {
i=j+2*r-1;//能够贪心选择最远房间的位置
ans++;
flag=0;
cur=j;//保存现在选择房间的位置
}
}
if(flag) break;//没有找到满足条件的房间
if(cur+r-1>=n) break;//已经覆盖了所有房间
if(i>n) i=n;
}
printf("%d\n",flag==1?-1:ans);
}
C.ブックスクエリ
質問の意味:双方向のキューがあります。Lは右に、キューにこの要素のRの代表をこの要素の左側を表します。?多くの要素を代表して、少なくとも左端または右端キューキューにこの要素を削除するには、クエリを作ることができます。
ソリューション:アナログに直接双方向キューで開始しますが、データの範囲が大きすぎT. 慎重に一瞬思ったの背後に、私はキューに時間要素を追加するたびに、私は時間の要素をチェックするとき、彼は、左端または右端のセクションをキューイングしなければいけません限りバックは比較的新しく追加されたとしてではなく、どのように多くのLどのように多くのRだけで罰金。
例えば、私は要素L1を照会したいです
状況がキューL1 LLRRRようなものであるとき、L1が追加されているものと、3つの放電キューを残し、キュー3は右に置きます。
いま、私はキューがLL L1 LLRRRR L1の時間に更新されている見つけなければならないとき。
あなたはL1は、左端の要素になるようにしたい場合は、それは、クエリの左側のセクションにある要素の数、追加マイナスL1時間左の要素数です。これは、5-3 = 2です。
あなたはL1が極端に右の要素になるよう、そしてそれは、クエリの要素の右の数である、プラスL1を追加したい場合は数-1左の要素です。即ち4+(3-1)= 6。
この要素は、それのための時間が追加されていることをどのようにすばやく見つけます。私たちは、[MAXN]配列のPOSを定義することができます。別のPOSは[L1] =私は、要素の位置を保存することができます。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6;
int pos[maxn];
struct node{
int l,r;//保存此时放队列左边的个数,以及放右边的个数
int id;//1表示这个元素放左边,2表示这个元素放右边
}e[maxn];
int main()
{
int n,l=0,r=0;
cin>>n;
for(int i=1;i<=n;i++){
getchar();
char c;int x;
cin>>c>>x;
if(c=='L') l++,e[i].id=1;
if(c=='R') r++,e[i].id=2;
if(c=='?'){
int ans=0;
if(e[pos[x]].id==1){
ans = min(l-e[pos[x]].l,r+e[pos[x]].l-1);
}
if(e[pos[x]].id==2){
ans = min(r-e[pos[x]].r,l+e[pos[x]].r-1);
}
cout<<ans<<endl;
continue;
}
e[i].l=l;e[i].r=r;
pos[x]=i;//保存这个元素在结构体的位置
}
}
E. 2進数和
この電子は、簡単な質問、不思議のXLS 10分の秒をノックし、ゲームは、この問題のqwqを見ていなかった時に後悔します。
質問の意味:あなたは2つの2進数を与えるが01列で、文字列は、各列右1 B、移動しません。各文字列と一緒にした後に移動した後に得られた文字列B&結果bが0になるまで。
ソリューション:接頭辞+速いとパワー。当初、私はそれが大きな数の問題だと思ったし、その後パリティの位置などを考えます。。。アイデアの混乱。そして最後に、実際にはそれほど複雑ではないことを発見しました。
常に後方に配列bは、動いていません。だから、すべての1のために、そうではありませんとになり、彼の列b 1つの前にすべてのポジション貢献それに答えます。
例えば= 10001、B = 1110011
10001 10001 10001 10001 10001 10001 10001
1110011 111001 11100 1110 111 11 1
最大1のアレイのビットのために、アレイはなり3及び1 * 2 ^ 3回の最高レベルは4とBに応答し、1ビットのアレイの最小ため、アレイは、B相1つの回答に全5 * 2 ^ 0に貢献します
最後に、答えは53です
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5+100;
const ll mod =998244353;
int sum[maxn];
char s1[maxn],s2[maxn];
ll powmod(ll a,ll b) {ll res=1;a%=mod; //快速幂
for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
int main()
{
int n,m;
cin>>n>>m>>s1+1>>s2+1;
for(int i=1;i<=m;i++){//求前缀和
if(s2[i]=='1') sum[i]=sum[i-1]+1;
else sum[i]=sum[i-1];
}
ll ans=0;
int t=m-n;//m和n不一样,t的作用是将他们的位置对齐
for(int i=n;i>=1;i--)//因为后面才是低位,所以从后面往前遍历
if(s1[i]=='1'&&i+t>=1)//t位负数时,i+t可能为负数
ans=(ans+powmod(2,(n-i))*sum[i+t])%mod;
cout<<ans<<endl;
}