Problem A 腿部挂件

  给出$n$个数的序列$a_i$,支持$T$次操作。

  每次操作形如$x , l , r$,计算$\max_{i = l}^{r} (a_i \oplus x)$的值。

  对于$100\%$的数据满足$1 \leq n \leq 2 \times 10^5 , 0 \leq a_i \leq 10^9$

Solution :

  通常可以使用可持久化字典树求解,但是这里可以用字典树套vector来做。

  这样当当前节点vector有一个在$l,r$的数中就往下走,还是按照以前的贪心策略,从高位到低位贪心。

  这样做的时间复杂度是$O(n {log_2} ^2 n)$

#include<bits/stdc++.h>
#define pb push_back
using namespace std;
struct node
{
vector<int>p;
int ls,rs;
node(){ls=rs=-;}
}tr[];
int n,m,a,x,y,cnt,o[];
void push(int k,int p)
{
for(int i=-,nw=;i>=;i--)
{
if(k&o[i])
{
if(tr[nw].ls==-)tr[nw].ls=++cnt;
nw=tr[nw].ls;
}
else
{
if(tr[nw].rs==-)tr[nw].rs=++cnt;
nw=tr[nw].rs;
}
tr[nw].p.pb(p);
}
}
int query(int k,int l,int r)
{
int ans=;
for(int i=-,nw=;i>=;i--)
{
if(k&o[i])
{
if(tr[nw].rs==-||*(tr[tr[nw].rs].p.end()-)<l||*lower_bound(tr[tr[nw].rs].p.begin(),tr[tr[nw].rs].p.end(),l)>r)
nw=tr[nw].ls,ans+=o[i];
else nw=tr[nw].rs;
}
else
{
if(tr[nw].ls==-||*(tr[tr[nw].ls].p.end()-)<l||*lower_bound(tr[tr[nw].ls].p.begin(),tr[tr[nw].ls].p.end(),l)>r)
nw=tr[nw].rs;
else nw=tr[nw].ls,ans+=o[i];
}
}
return ans^k;
}
int main()
{
freopen("hugclose.in","r",stdin);
freopen("hugclose.out","w",stdout);
scanf("%d%d",&n,&m),o[]=cnt=;
for(int i=;i<;i++)o[i]=o[i-]*;
for(int i=;i<=n;i++)scanf("%d",&a),push(a,i);
for(int i=;i<=m;i++)scanf("%d%d%d",&a,&x,&y),printf("%d\n",query(a,x+,y+));
return ;
}

hugclose.cpp

Problem B 走夜路

  一条直线上有n+1个充电站,一开始你在第一个充电站,每个充电站都能以某个代价充电

  每走一个单位距离就要耗费一单位电,求按顺序走完所有充电站的最小代价

  对于$100\%$的数据满足$1 \leq n \leq 5\times 10^5$

Solution  :

  考虑一种贪心,依次考虑每一个充电站。

   下一个充电站优先级从高到低依次是:

  • 当前充电站以后第一个费用小于当前充电站(此时,直接在当前充电站充满恰好能到下个充电站的电,然后直接走到那个充电站即可)
  • 终点(如果当前充电站冲一定的点之后能到终点,那么就直接到达终点)
  • 在充满电后能走到的所有充电站中,费用最小的充电站(此时需要先在当前充电站充满电后再移动)

  可以考虑使用单调栈来求对于每个位置右侧第一个小于它的数,(从前往后加入数,满足栈单调增,弹栈的时候记录即可)

  然后再使用小常数的$st$表来求出静态区间最小值并且维护标号。

  所以,本题就是$O(n log_2 n)$的复杂度了。

#pragma GCC optimize(3)
# include <bits/stdc++.h>
using namespace std;
const int N=+;
int st[<<][],id[<<][];
# define int long long
int n,T,d[N],a[N],r[N];
stack<int>s;
int dist(int x,int y) { if (x>y) swap(x,y); return d[y-]-d[x-];}
namespace fast_IO{
const int IN_LEN = , OUT_LEN = ;
char ibuf[IN_LEN], obuf[OUT_LEN], *ih = ibuf + IN_LEN, *oh = obuf, *lastin = ibuf + IN_LEN, *lastout = obuf + OUT_LEN - ;
inline char getchar_(){return (ih == lastin) && (lastin = (ih = ibuf) + fread(ibuf, , IN_LEN, stdin), ih == lastin) ? EOF : *ih++;}
inline void putchar_(const char x){if(oh == lastout) fwrite(obuf, , oh - obuf, stdout), oh = obuf; *oh ++= x;}
inline void flush(){fwrite(obuf, , oh - obuf, stdout);}
int read(){
int x = ; int zf = ; char ch = ' ';
while (ch != '-' && (ch < '' || ch > '')) ch = getchar_();
if (ch == '-') zf = -, ch = getchar_();
while (ch >= '' && ch <= '') x = x * + ch - '', ch = getchar_(); return x * zf;
}
void write(int x){
if (x < ) putchar_('-'), x = -x;
if (x > ) write(x / );
putchar_(x % + '');
}
}
using namespace fast_IO;
void build() {
memset(st,0x3f,sizeof(st));
for (int i=;i<=n;i++) st[i][]=a[i],id[i][]=i;
for (int i=;i<=;i++)
for (int j=;j<=n;j++)
if (st[j][i-]<st[j+(<<(i-))][i-]) {
st[j][i] = st[j][i-];
id[j][i] = id[j][i-];
} else {
st[j][i] = st[j+(<<(i-))][i-];
id[j][i] = id[j+(<<(i-))][i-];
}
}
int LOG[N];
int query(int l,int r) {
int k=LOG[r-l+];
if (st[l][k] < st[r-(<<k)+][k]) return id[l][k];
else return id[r-(<<k)+][k];
}
signed main()
{
n=read();T=read();
for (int i=;i<=n;i++) LOG[i] = log2(i);
for (int i=;i<=n;i++) d[i]=read(),a[i]=read();
build();
while (!s.empty()) s.pop();
for (int i=n;i>=;i--) {
while (!s.empty()&&a[s.top()]>=a[i]) s.pop();
if (s.empty()) r[i]=n; else r[i]=s.top()-;
s.push(i);
}
for (int i=;i<=n;i++)
r[i] = (r[i]==n)?(-):(r[i]+),
d[i] += d[i-];
int now = , res = ;
int cost = ;
while (true) {
if (r[now]!=- && dist(r[now] , now) <= T) {
if (res >= dist(r[now], now)) res-=dist(r[now],now);
else cost += 1ll * a[now]*(dist(r[now], now)-res),res = ;
now = r[now];
} else if (dist(n+,now) <= T) {
if (res >= dist(n+, now)) res-=dist(n+,now);
else cost += 1ll * a[now]*(dist(n+,now)-res),res = ;
break;
} else {
cost += 1ll * (T-res)*a[now];
int l = now+, r = n , ans = -;
while (l<=r) {
int mid = (l+r) >> ;
if (dist(mid,now)<=T) ans=mid,l=mid+;
else r = mid-;
}
if (ans == -) {
write(-); flush(); return ;
}
int to = query(now+,ans);
res = T - dist(to , now);
now = to;
}
}
write(cost); flush();
return ;
}

wayhome.cpp

Problem C 宝石专家

 给出$n$个数的序列$a_i$,处理$T$个询问,

 每个询问形如$l,r$,请输出在$a_l ... a_r$中两个相同的数的最近距离。

 若$a_x = a_y$,那么距离定义为$|x- y|$

 对于$100\%$的数据,满足$1 \leq n,T\leq 2 \times 10^5$

Solution :

  首先,我们发现对于相同的数,在一些位置,只有相邻的两个数所构成的线段有意义。

  所以需要处理的小线段长度在$n$这个级别。

  我们考虑将操作离线,放在一个$[1,n]$的数轴上,并考虑从$n$到$1$依次扫。

  如果当前遇到了一个小线段的左端点$l$,那么在线段树中$[r,n]$用这条线段的权值$r-l$来更新答案。

  所以,线段树的意义是扫到当前位置,询问线段的右端点的答案。

  所以,如果遇到一个询问线段,那么直接求出$[l,r]$的最小值即可,但是由于值的单调性,直接单点求出$r$的值即可。

  时间复杂度就是$O(n log_2 n)$。

#pragma GCC optimize(3)
# include <bits/stdc++.h>
# define inf (0x3f3f3f3f)
using namespace std;
const int N = 2e5 + ;
vector<int>tmp;
vector<int>v[N];
vector< pair<int,int> >r[N],qes[N];
int n,m,a[N],ans[N];
namespace fast_IO{
const int IN_LEN = , OUT_LEN = ;
char ibuf[IN_LEN], obuf[OUT_LEN], *ih = ibuf + IN_LEN, *oh = obuf, *lastin = ibuf + IN_LEN, *lastout = obuf + OUT_LEN - ;
inline char getchar_(){return (ih == lastin) && (lastin = (ih = ibuf) + fread(ibuf, , IN_LEN, stdin), ih == lastin) ? EOF : *ih++;}
inline void putchar_(const char x){if(oh == lastout) fwrite(obuf, , oh - obuf, stdout), oh = obuf; *oh ++= x;}
inline void flush(){fwrite(obuf, , oh - obuf, stdout);}
int read(){
int x = ; int zf = ; char ch = ' ';
while (ch != '-' && (ch < '' || ch > '')) ch = getchar_();
if (ch == '-') zf = -, ch = getchar_();
while (ch >= '' && ch <= '') x = x * + ch - '', ch = getchar_(); return x * zf;
}
void write(int x){
if (x < ) putchar_('-'), x = -x;
if (x > ) write(x / );
putchar_(x % + '');
}
}
using namespace fast_IO;
struct Seg {
int val,tag;
Seg() { val = tag = inf;}
}tr[N<<];
# define lson ls,l,mid
# define rson rs,mid+,r
# define mid (l+r>>)
# define ls (x<<)
# define rs (x<<|)
void down(int x) {
tr[ls].val=min(tr[ls].val,tr[x].tag);
tr[rs].val=min(tr[rs].val,tr[x].tag);
tr[ls].tag=min(tr[ls].tag,tr[x].tag);
tr[rs].tag=min(tr[rs].tag,tr[x].tag);
tr[x].tag = inf;
}
void update(int x,int l,int r,int opl,int opr,int val) {
if (opl <= l && r <= opr) {
tr[x].tag = min(tr[x].tag , val);
tr[x].val = min(tr[x].val , val);
return;
}
down(x);
if (opl<=mid) update(lson,opl,opr,val);
if (opr> mid) update(rson,opl,opr,val);
tr[x].val = min(tr[ls].val , tr[rs].val);
}
int query(int x,int l,int r,int pos) {
if (l == r) return tr[x].val;
down(x);
if (pos<=mid) return query(lson,pos);
else return query(rson,pos);
}
int main()
{
n=read();m=read();
for (int i=;i<=n;i++) {
tmp.push_back(a[i]=read());
}
sort(tmp.begin(),tmp.end());
tmp.erase(unique(tmp.begin(),tmp.end()),tmp.end());
for (int i=;i<=n;i++) {
a[i] = lower_bound(tmp.begin(),tmp.end(),a[i]) - tmp.begin()+;
v[a[i]].push_back(i);
}
for (int i=;i<=n;i++) {
if (v[i].size() < ) continue;
for (int j=;j<v[i].size()-;j++)
r[v[i][j]].push_back(make_pair(v[i][j+],v[i][j+]-v[i][j]));
}
for (int i=;i<=m;i++) {
int l=read(),r=read();
qes[l].push_back(make_pair(r,i));
}
for (int i=n;i>=;i--) {
int sz = r[i].size();
if (sz) {
for (int j=;j<sz;j++)
update(,,n,r[i][j].first,n,r[i][j].second);
}
sz = qes[i].size();
if (sz) {
for (int j=;j<sz;j++)
ans[qes[i][j].second] = query(,,n,qes[i][j].first);
}
}
for (int i=;i<=m;i++) {
write((ans[i]>=inf)?-:ans[i]); putchar_('\n');
}
flush();
return ;
}

jewel.cpp

HGOI 20191030am 题解的更多相关文章

  1. HGOI 20181028 题解

    HGOI 20181028(复赛备考) /* 真是暴力的一天,最后一题MLE?由于数组开得太大了!!! 270滚粗 考场上好像智商高了很多?!(假的) */ sol:暴力求解,然后没有数据范围吐槽一下 ...

  2. HGOI 20190310 题解

    /* 又是又双叒叕WA的一天... 我太弱鸡了... 今天上午打了4道CF */ Problem 1 meaning 给出q组询问,求下列函数的值$ f(a) = \max\limits_{0 < ...

  3. HGOI 20190303 题解

    /* 记一串数字真难. 5435 今天比赛又是hjcAK的一天. 今天开题顺序是312,在搞T1之前搞了T3 昨天某谷月赛真是毒瘤. 但是讲评的同学不错,起码T4看懂了... 构造最优状态然后DP的思 ...

  4. HGOI 20180224 题解

    /* The Most Important Things: ljc chat with fyh on QQTa说期末考Ta数学74分感觉不好但是我觉得fyh是地表最强的鸭~~(of course en ...

  5. HGOI 20190218 题解

    /* 又是AK局... hjc又双叒叕AK了... Hmmm...我侥幸 */ Problem A card 给出无序序列a[]可以选择一个数插入到合适的位置作为一次操作,至少多少次操作后可以把序列变 ...

  6. HGOI 20190217 题解

    /* for me,开训第一天 /beacuse 文化课太差被抓去补文化课了... 看一眼题 : AK局? 但是,Wa on test #10 in problem C 290! (就差那么一咪咪) ...

  7. HGOI 20181103 题解

    problem:把一个可重集分成两个互异的不为空集合,两个集合里面的数相乘的gcd为1(将集合中所有元素的质因数没有交集) solution:显然本题并不是那么容易啊!考场上想了好久.. 其实转化为上 ...

  8. HGOI 20181101题解

    /* 又是爆0的一天(不知道今年高考难不难,反正今天(信息学)真的难!) */ solution:对于两个数相加,有一个显然的结论就是要么不进位(相对于位数大的),要么(进最多一位) 然后对于整个数组 ...

  9. HGOI 20191108 题解

    Problem A 新婚快乐 一条路,被$n$个红绿灯划分成$n+1$段,从前到后一次给出每一段的长度$l_i$,每走$1$的长度需要$1$分钟. 一开始所有红绿灯都是绿色的,$g$分钟后所有红绿灯变 ...

随机推荐

  1. 安装 pybloomfilter

    1.在windows的cmd下,使用 pip install pybloomfiltermmap 命令安装,pybloomfiltermmap 时报错 ,错误信息如下 根据错误信息分析,报错原因是需要 ...

  2. UI语言杂集

    最适合做 GUI 的是 DSL 或者 XML(以及 XML 的扩展)之类的标记语言,而不是编程语言. 例如 Qt 的 QML,Android 的 XML 或者 WPF 的 XAML 以及大家都再熟悉不 ...

  3. 怎样理解DOM

    一句话总结: DOM 是一个 js 对象. 他可以赋予 js 控制 html 文档的能力.  全称: Document Object Model. DOM 的最小组成单位是: 节点 , 节点有7种类型 ...

  4. 实现表单label两端对齐

    主要使用css3属性 text-align: justify; text-align-last: justify; 上代码: <ul> <li> <label class ...

  5. Hadoop 上Hive 的操作

    数据dept表的准备: --创建dept表 CREATE TABLE dept( deptno int, dname string, loc string) ROW FORMAT DELIMITED ...

  6. 用qpython3写一个发送短信的程序

    用qpython3写一个最简单的发送短信的程序 用qpython3写一个最简单的发送短信的程序到目前为止并没有多少手机应用是用python开发的,不过qpython可以作为一个不错的玩具推荐给大家来玩 ...

  7. deep_learning_Function_list变量前面加星号,字典变量前面加两个星号

    列表前面加星号作用是将列表解开成两个独立的参数,传入函数, 字典前面加两个星号,是将字典解开成独立的元素作为形参. def add(a, b): return a+b data = [4,3] pri ...

  8. 建立一个可以不停地接收客户端新的连接,但不能处理复杂的业务的C/S网络程序

    在Windows平台上主要有两个版本的Socket Api函数:WinSock 1.1和WinSock 2.2 , 2.2版本默认兼容1.1版本,1.1 winsock.h wsock32.lib w ...

  9. oracle学习1 基于oracle数据库的PLSQL编程以及存储过程的创建和使用视频

    https://www.bilibili.com/video/av46777605 plsql中选择testWindow中可以进行测试 1.编写函数在plsql的testwindow中 begin d ...

  10. python3.6 错误: ModuleNotFoundError:No module named "Crypto"

    原因及处理:在使用python是经常会用到import一个第三方库,但是有时候会提示某个模块不存在,如Crypto其实是因为Python3里面这个模块的名字变了, pip install pycryp ...