9月14日:
luogu P1627 [CQOI2009]中位数
题意:给出1~n的一个排列,统计该排列有多少个长度为奇数的连续子序列的中位数是b。中位数是指把所有元素从小到大排列后,位于中间的数。
一句话题解:根据中位数的性质,将大于b的数记为1,小于b的数记为-1,区间和为0的奇数序列即符合题意,再计数即可。
#include<bits/stdc++.h>
#define ll long long
#define mp make_pair
#define rep(i, a, b) for(int i = (a);i <= (b);i++)
#define per(i, a, b) for(int i = (a);i >= (b);i--)
using namespace std;
typedef pair<int, int> pii;
typedef double db;
const int N = 1e6 + 50;
int n, b, a[N], lsum[N], rsum[N];
int l[N], r[N], minn = N, maxx = 0;
int pos;
ll ans = 0;
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}
while(ch >='0' && ch <='9'){x = (x<<3)+(x<<1)+(ch^48); ch = getchar();}
return x*f;
}
int main(){
n = read(); b = read();
rep(i, 1, n){
a[i] = read();
if(a[i] < b) a[i] = -1;
if(a[i] == b) a[i] = 0, pos = i;
if(a[i] > b) a[i] = 1;
}
rep(i, pos+1, n) rsum[i] = rsum[i-1] + a[i], minn = min(minn, rsum[i]+n);
per(i, pos-1, 1) lsum[i] = lsum[i+1] + a[i], minn = min(minn, lsum[i]+n);
l[n] = r[n] = 1;
rep(i, pos+1, n) r[rsum[i]+n]++;
per(i, pos-1, 1) l[lsum[i]+n]++;
maxx = 2*n-minn;
rep(i, minn, maxx){
ans += (ll)l[i] * r[2*n-i];
}
printf("%lld\n", ans);
return 0;
}
luogu P3407 散步
题意:数轴上有n个人,每秒钟在给定的方向(向东或向西)移动一个距离,当一个人与一个人相遇时两人不再移动,求t秒后,指定m个人所在的位置。
一句话题解:预处理出相遇点,然后二分答案与pos+t进行比较即可。
#include<bits/stdc++.h>
#define ll long long
#define mp make_pair
#define rep(i, a, b) for(int i = (a);i <= (b);i++)
#define per(i, a, b) for(int i = (a);i >= (b);i--)
using namespace std;
typedef pair<int, int> pii;
typedef double db;
const int N = 1e6 + 50;
const ll inf = 4557430888798830399;
ll n, t, q;
ll s[N], k = 0;
struct people{ll pos, dic, id; } a[N];
bool mycmp(people a, people b) {return a.pos < b.pos; }
inline ll read(){
ll x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}
while(ch >='0' && ch <='9'){x = (x<<3)+(x<<1)+(ch^48); ch = getchar();}
return x*f;
}
int main(){
n = read(); t = read(); q = read();
rep(i, 1, n) a[i].pos = read(), a[i].dic = read(), a[i].id = i;
sort(a+1, a+n+1, mycmp);
rep(i, 2, n){
if(a[i].dic == 2 && a[i-1].dic == 1) s[++k] = (a[i].pos+a[i-1].pos)>>1;
}
s[0] = -inf, s[k+1] = inf;
rep(i, 1, q){
ll x = read();
ll posx = a[a[x].id].pos, flag = a[a[x].id].dic;
ll l = 1, r = k, mid;
while(l < r){
mid = (l+r)>>1;
if(flag == 1){
if(s[mid] < posx) l = mid+1;
if(s[mid] > posx) r = mid;
}
if(flag == 2){
if(mid == l) mid++;
if(s[mid] < posx) l = mid;
if(s[mid] > posx) r = mid-1;
}
}
mid = l;
if(s[mid] < posx && flag == 2){
if(s[mid+1] < posx && s[mid+1] != inf) mid++;
}
if(s[mid] > posx && flag == 1){
if(s[mid-1] > posx && s[mid-1] != inf) mid--;
}
if(flag == 1){
if(s[mid] > posx+t && s[mid] > posx) printf("%lld\n", posx+t);
else if(s[mid] < posx) printf("%lld\n", posx+t);
else if(s[mid] < posx+t && s[mid] > posx) printf("%lld\n", s[mid]);
else printf("%lld\n", s[mid]);
}
if(flag == 2){
if(s[mid] < posx-t && s[mid] < posx) printf("%lld\n", posx-t);
else if(s[mid] > posx-t && s[mid] < posx) printf("%lld\n", s[mid]);
else if(s[mid] > posx) printf("%lld\n", posx-t);
else printf("%lld\n", s[mid]);
}
}
return 0;
}