D
- 問題の意味:の配列、[I]戻りますループのそれぞれについて、最初まで({[I]} {2} [J \ N-%] <\ FRAC \)\、Q各[i]は数歩の距離高々 。
- 彼または後ろに、2例があるため、(そうでなければ-1、[i]は、最大2 * nのそれぞれを歩く)を3回繰り返し[i]はカードである:のことを考えて\([j個の\%nを<\ FRAC {[I]} {2} \) 、または[J]である> [I ]、 [J]は注釈を維持する具体的方法については、[i]はカードよりも容易であるように
#include<bits/stdc++.h>
#define ll long long
#define pii pair<int,int>
using namespace std;
int main(){
int n; cin >> n;
vector<int> a(3*n);
for(int i=0;i<n;++i){
cin >> a[i]; a[i+n] = a[i+n+n] = a[i];
}
vector<int> ans(3*n);
vector<int> st_max,st_min;
for(int i=3*n-1;i>=0;--i){
while(st_max.size() && a[st_max.back()] < a[i]) st_max.pop_back(); // 单调减
while(st_min.size() && a[st_min.back()] > a[i]) st_min.pop_back(); // 单调增
int low = 0, high = st_min.size(); // 二分找卡 a[i]的点
while(low < high){
int mid = (low + high) >> 1;
if(a[st_min[mid]]*2 <a[i]) // 卡a的点都在单调增栈中
low = mid+1;
else high = mid;
}
int nxt = 3*n; // 最后一个 相当于没找到
if(low > 0) nxt = min(nxt,st_min[low-1]); // 找得到更新nxt
if(!st_max.empty()) nxt = min(nxt,st_max.back()); // 单调减栈中的值肯定比a[i]大,且在i后面,比a[i]更易被卡
if(nxt < 3*n && a[nxt] >= a[i]) ans[i] = ans[nxt]; // nxt 被卡
else ans[i] = nxt; // i被nxt卡
st_min.push_back(i);
st_max.push_back(i);
}
for(int i=0;i<n;++i){
if(i>0) cout << ' ';
cout << (ans[i]==3*n?-1:ans[i]-i) ;
}
cout << '\n';
return 0;
}
- メンテナンスは、スタックの半分に単調に増加単調性、および単調ことができます。
- 額面はフロント、とても奥から手前に統計に影響しますので。
C
- 問題の意味:3次元空間の中でいくつかの点は、それぞれの時間は、次の2つのポイントが削除されていない選択して削除することはできませんか、他の二つの点で長方形の内部境界点は、プログラムを削除しようとしています。
- アイデア:直接の順序は、最初の最初の二つの次元が同じポイント、ポイント右に隣接する第3順位の位置の後に削除された同じ点の最初の次元を削除するための第2の時間である削除します。
#include<bits/stdc++.h>
#define ll long long
#define pii pair<int,int>
using namespace std;
const int N = 5e5+10;
struct node{
int x,y,z,id;
}a[N];
int n,vis[N];
bool cmp(node p1,node p2){
if(p1.x!=p2.x) return p1.x < p2.x;
if(p1.y!=p2.y) return p1.y < p2.y;
return p1.z < p2.z;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;++i){
scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);
a[i].id = i;
}
sort(a+1,a+1+n,cmp);
for(int i=1;i<=n-1;++i){
if(a[i+1].x == a[i].x && a[i+1].y == a[i].y){
vis[i] = vis[i+1] = 1;
printf("%d %d\n",a[i].id,a[i+1].id);
i++;
}
}
for(int i=1;i<=n-1;++i){
if(vis[i]) continue;
int j = i+1;
while(vis[j]) j++;
if(a[i].x == a[j].x){
vis[i] = vis[j] = 1;
printf("%d %d\n",a[i].id,a[j].id);
i = j; // i到j全部被访问过, 直接跳避免n^2复杂度
}
}
for(int i=1;i<=n-1;++i){
if(vis[i]) continue;
int j = i+1;
while(vis[j]) j++;
vis[i] = vis[j] = 1;
printf("%d %d\n",a[i].id,a[j].id);
i = j;
}
return 0;
}
B
- 質問の意味:車の行は、初期位置と最終位置があり、彼は車を追い越しどのように多く尋ね
- アイデア:後ろから前にプッシュは、より車のメンテナンス上の車両の現在位置の初期位置した後、現車を追い越すために、車の中で最も前方の初期位置を維持します。
#include<bits/stdc++.h>
#define ll long long
#define pii pair<int,int>
using namespace std;
const int N = 1e5+10;
int a[N],n,pos[N],b[N],c[N];
int main(){
ios::sync_with_stdio(false);
cin >> n;
for(int i=1;i<=n;++i) {
cin >> a[i] , pos[a[i]] = i;
}
int val,cnt = 0,ans = 0,dif;
for(int i=1;i<=n;++i){
cin >> val;
b[i] = pos[val];
}
c[n] = b[n];
for(int i=n-1;i>=1;--i){
c[i] = min(c[i+1],b[i]);
}
for(int i=1;i<n;++i){
if(b[i]>c[i+1]) ans++;
}
cout << ans << '\n';
return 0;
}
観光客主はただ死んでパズルカード、QAQの外に私を置きます我々は右、地域の大会に文字を保存することを望んでいます