题意:询问区间唯一元素个数,单点修改。

分析

借助Unique snowflakes, Can you answer these queries II的思想,唯一性可以借助元素上一次出现的位置来判断。

对于询问(x,y),只要回答[x,y)区间内,上一次出现位置prv[i] < x的元素数量即可。

对于修改来说,如果原来的a[x]的后继元素存在,则要修改后继的前驱。

a[x]修改成y以后,找到x位置前的y出现位置,作为x位置的前驱,并修改x位置以后下一个y的前驱。

寻找前驱后继可以用一个set保存(value,pos)的二元组,平方分解可以更暴力地找。

目前已知实现方法有三种,1.线段树套平衡树,2.平方分解,3.BIT套函数式线段树。

线段树套一个平衡树,想要偷懒试了试pb_ds里面的rb_tree,但是join的时候值域不能相交,并且只能nlognlogn建树。O((n+m)lognlogn)

改成套SBT,可以做到nlogn建线段树,然后写挂了。(实际上是我不知道SBT删除的时候怎么maintain。也许改成Treap或者BST会过。)。O(nlogn + mlognlogn)

平方分解,比较容易写,10s时限很稳。O(nlogn + m(N/BlogB+BlogB)) = O(nlogn + N^(3/2)log(N^(1/2)))

BIT套函数式,好写,内存消耗大(UVA的内存没有限制吗?)。O(nlogn,mlognlogn)

(实在过不了的话,因为暴力修改是O(1),可以水过...

#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp> using namespace std;
using namespace __gnu_pbds; typedef pair<int,int> pii; typedef long long ll; const int maxn = 5e4+; #define value first
#define index second
tree <pii,null_type> SET; #define para Node *(&o), int l = 0, int r = n
#define lo (o->lch)
#define ro (o->rch)
#define Tvar int md = (l+r)>>1;
#define lsn lo,l,md
#define rsn ro,md,r
#define insd x<=l&&r<=y const int maxd = ;
const int maxnds = maxd*maxn*maxd;
struct Node
{
Node *lch,*rch;
int s;
}meo[maxnds]; int a[maxn];
int *const ps = (int*)(meo+);
int prv[maxn];
int n; Node *root[maxn]; Node *const nil = meo;
Node *freeNode = nil; void build(int v,para)
{
*(++freeNode) = *o;
o = freeNode;
o->s++;
if(r-l == ) return;
Tvar
if(v < md) build(v,lsn);
else build(v,rsn);
} void inst(int v,int d,para)
{
if(o == nil){
*(++freeNode) = *o;
o = freeNode;
}
o->s += d;
if(r-l == ) return;
Tvar
if(v < md) inst(v,d,lsn);
else inst(v,d,rsn);
} Node *BIT[maxn]; typedef vector<Node*> Prefix; Prefix X,Y; void q_pfx_bit(int x, Prefix &res)
{
res.clear();
while(x > ){
res.push_back(BIT[x]);
x &= x-;
}
} void modify_bit(int x,int v,int d)
{
while(x <= n){
inst(v,d,BIT[x]);
x += x&-x;
}
} inline int cal_lft(Prefix &p)
{
int cnt = ;
for(auto &nd: p){
cnt += nd->lch->s;
}
return cnt;
} inline int cal_sum(Prefix &p)
{
int cnt = ;
for(auto &nd: p){
cnt += nd->s;
}
return cnt;
} #define dump(P,ch)\
for(auto &nd: P){\
nd = nd->ch;\
} int query(int v, int l = ,int r = n)
{
if(r<=v) return cal_sum(Y)-cal_sum(X);
Tvar
if(v <= md) {
dump(X,lch) dump(Y,lch)
return query(v,l,md);
}
int tmp = cal_lft(Y)-cal_lft(X);
dump(X,rch) dump(Y,rch)
return tmp + query(v,md,r);
} inline void modify(int x,int y)
{
modify_bit(x,prv[x],-);
modify_bit(x,prv[x]=y,);
} //#define LOCAL
int main()
{
#ifdef LOCAL
freopen("data.txt","r",stdin);
#endif
//cout<<maxnds;
nil->lch = nil->rch = nil;
root[] = nil;
int m;
scanf("%d%d",&n,&m); for(int i = ; i <= n; i++) {
scanf("%d",a+i);
prv[i] = ps[a[i]];
ps[a[i]] = i;
SET.insert(pii(a[i],i));
} for(int i = ; i <= n; i++){
root[i] = root[i-];
build(prv[i],root[i]);
} fill(BIT+,BIT+n+,nil);
char op[];
int x,y;
while(m--){
scanf("%s%d%d",op,&x,&y); //0 based
if(*op == 'Q'){
q_pfx_bit(x,X);
q_pfx_bit(y,Y);
X.push_back(root[x]);
Y.push_back(root[y]);
printf("%d\n",query(x+));
}
else {
x++;
if(a[x] == y) continue; //...
auto it = SET.lower_bound(pii(a[x],x+));
if(it != SET.end() && it->value == a[x]){
modify(it->index,prv[x]);
} it = SET.lower_bound(pii(y,x));//找后继,需要保证(y,x)不存在 if(it != SET.end() && it->value == y){
modify(it->index,x);
} modify(x,(it != SET.begin() && (--it)->value == y)? it->index : ); SET.erase(pii(a[x],x));
SET.insert(pii(a[x] = y,x));
}
}
return ;
}

UVA 12345 Dynamic len(set(a[LR]))的更多相关文章

  1. UVA 12345 Dynamic len(带修莫队)

    Dynamic len [题目链接]Dynamic len [题目类型]带修莫队 &题解: 莫队可以单点更改,只要再多加一维,代表查询次数,排序的时候3个关键字. 之后循环离线的时候,先暴力时 ...

  2. Uva 3767 Dynamic len(set(a[L:R])) 树套树

    Dynamic len(set(a[L:R])) Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 https://uva.onlinejudge.org/in ...

  3. (待修莫队 没过! 抽空在检查)Dynamic len(set(a[L:R])) UVA - 12345

    #include <iostream> #include <cstdio> #include <sstream> #include <cstring> ...

  4. Dynamic len(set(a[L:R])) UVA - 12345(这么过分一定要写博客)

    给出一个有n个元素的数组,有以下两种操作:Q x y,求出区间[x,y)内不同元素的个数, M x y,把第x个元素的值修改为y.注意题目中的下标是从0开始的 这题超级超级坑 妈的一个水题找了几个小时 ...

  5. UVA 11990 ``Dynamic'' Inversion 动态逆序对

    ``Dynamic'' Inversion Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 https://uva.onlinejudge.org/index ...

  6. UVA 11990 `Dynamic'' Inversion CDQ分治, 归并排序, 树状数组, 尺取法, 三偏序统计 难度: 2

    题目 https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&a ...

  7. 【题解】Luogu UVA12345 Dynamic len(set(a[L:R]))

    原题传送门 这题要用动态莫队,我博客里有介绍 这道题和luogu P1903 [国家集训队]数颜色 / 维护队列差不多,解法就在上面那篇博客里qaq 主要的问题是如何排序? 排序有三个关键字: 1.左 ...

  8. UVA 11990 ”Dynamic“ Inversion(线段树+树状数组)

    [题目链接] UVA11990 [题目大意] 给出一个数列,每次删去一个数,求一个数删去之前整个数列的逆序对数. [题解] 一开始可以用树状数组统计出现的逆序对数量 对于每个删去的数,我们可以用线段树 ...

  9. UVA 11990 ``Dynamic'' Inversion (序列分治)

    26天以前做过的一道题,之前的做法是分治预处理,树套树在线修改,复杂度为O(nlogn+m*logn*logn),代码量较大. 本来想学习一下cdq分治的,看到论文上的凸包.斜率就暂时放一边了,只知道 ...

随机推荐

  1. sqlserver 事务日志

    预写式日志(Write-Ahead Logging (WAL)) --在数据写入到数据库之前,先写入到日志. 1.”Begin Tran”记录  -> 缓冲区 2. 日志             ...

  2. Vue.js递归组件实现动态树形菜单

    使用Vue递归组件实现动态菜单 现在很多项目的菜单都是动态生成的,之前自己做项目也是遇到这种需求,翻看了官网案例,和网上大神的案例.只有两个感觉,官网的案例太简洁,没有什么注释,看起来不太好理解,大神 ...

  3. SSL证书切换

    SSL证书:SSL证书是数字证书的一种,类似于驾驶证.护照和营业执照的电子副本.因为配置在服务器上,也称为SSL服务器证书.SSL 证书就是遵守 SSL协议,由受信任的数字证书颁发机构CA,在验证服务 ...

  4. 标签li设为display inline-block后间距问题

    在对导航栏做水平排列的时候,我们往往对li元素设为display:inline-block 目的是为了,让所有li元素并排在一起,但是遇到个问题,我们的标签之间会产生空白边距 如图所示: 这样看上去, ...

  5. mac U盘安装盘制作

    以下面的版本为例: Install_macOS_Sierra_10.12.6.dmg 解压到桌面,然后打命令 sudo /Users/love/Desktop/Install\ macOS\ Sier ...

  6. POJ 3522 ——Slim Span——————【最小生成树、最大边与最小边最小】

    Slim Span Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 7102   Accepted: 3761 Descrip ...

  7. 【转】jsoup的使用

     Jsoup的使用   jsoup 是一款 Java 的HTML 解析器,可直接解析某个URL地址.HTML文本内容.它提供了一套非常省力的API,可通过DOM,CSS以及类似于JQuery的操作方法 ...

  8. promise之nodejsQ的详细用法总结

    这里主要讲node.js中Q的各种用法及说明总结,不详细介绍promise及原理.关于promise介绍可以查看我的另一篇文章: https://www.cnblogs.com/yzeng/p/976 ...

  9. Slickflow.NET 开源工作流引擎基础介绍-.NET Core2.0 版本实现介绍 (转)

    前言:.NET Core 是.NET Framework的新一代版本,是微软开发的第一个跨平台 (Windows.Mac OSX.Linux) 的应用程序开发框架(Application Framew ...

  10. jeecg3.8popup弹出窗口触发失去焦点事件,引发验证弹窗,影响体验问题的解决办法

    在初始化表单的代码中添加以下加粗部分,有几个popup就定义几个标志位,主要是防止第一次失去焦点时候的弹窗(此时还未来得及选择),提交表单的时候还是会正常校验的. //popup触发失去焦点事件,设置 ...