UVA 12345 Dynamic len(set(a[LR]))
题意:询问区间唯一元素个数,单点修改。
分析:
借助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]))的更多相关文章
- UVA 12345 Dynamic len(带修莫队)
Dynamic len [题目链接]Dynamic len [题目类型]带修莫队 &题解: 莫队可以单点更改,只要再多加一维,代表查询次数,排序的时候3个关键字. 之后循环离线的时候,先暴力时 ...
- 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 ...
- (待修莫队 没过! 抽空在检查)Dynamic len(set(a[L:R])) UVA - 12345
#include <iostream> #include <cstdio> #include <sstream> #include <cstring> ...
- Dynamic len(set(a[L:R])) UVA - 12345(这么过分一定要写博客)
给出一个有n个元素的数组,有以下两种操作:Q x y,求出区间[x,y)内不同元素的个数, M x y,把第x个元素的值修改为y.注意题目中的下标是从0开始的 这题超级超级坑 妈的一个水题找了几个小时 ...
- UVA 11990 ``Dynamic'' Inversion 动态逆序对
``Dynamic'' Inversion Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 https://uva.onlinejudge.org/index ...
- UVA 11990 `Dynamic'' Inversion CDQ分治, 归并排序, 树状数组, 尺取法, 三偏序统计 难度: 2
题目 https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&a ...
- 【题解】Luogu UVA12345 Dynamic len(set(a[L:R]))
原题传送门 这题要用动态莫队,我博客里有介绍 这道题和luogu P1903 [国家集训队]数颜色 / 维护队列差不多,解法就在上面那篇博客里qaq 主要的问题是如何排序? 排序有三个关键字: 1.左 ...
- UVA 11990 ”Dynamic“ Inversion(线段树+树状数组)
[题目链接] UVA11990 [题目大意] 给出一个数列,每次删去一个数,求一个数删去之前整个数列的逆序对数. [题解] 一开始可以用树状数组统计出现的逆序对数量 对于每个删去的数,我们可以用线段树 ...
- UVA 11990 ``Dynamic'' Inversion (序列分治)
26天以前做过的一道题,之前的做法是分治预处理,树套树在线修改,复杂度为O(nlogn+m*logn*logn),代码量较大. 本来想学习一下cdq分治的,看到论文上的凸包.斜率就暂时放一边了,只知道 ...
随机推荐
- PHP HTTP的PUT,DELETE的使用
GET操作是安全的.所谓安全是指不管进行多少次操作,资源的状态都不会改变.比如我用GET浏览文章,不管 浏览多少次,那篇文章还在那,没有变化.当然,你可能说每浏览一次文章,文章的浏览数就加一,这不也改 ...
- TCP/IP、Http、Https、Socket的区别
网络由下往上分为物理层.数据链路层.网络层( IP协议).传输层( TCP协议).会话层.表示层和应用层(HTTP协议) 接下来我来说说个人理解其中的TCP/IP.Http.Socket的区别 TCP ...
- Lambda 快速改造
对于只有一个参数的接口类,可以使用e->{} idea会给出快速提示 先写正常的表达式 将虚线处直接删掉, 在原来的方法参数和左大括号之间加上 -> 改造后比原来少了几行, 对于熟手阅读 ...
- my24_mysql索引-使用篇
索引提示 SELECT * FROM table1 USE INDEX (col1_index,col2_index) ; SELECT * FROM table1 IGNORE INDEX (col ...
- set与map
set /*set里面没有相同的元素 所以可以用于数组去重*/ //内部去重用的是=== 对象不等 但是 NaN等 //其本身是构造函数 let s=new Set([1,2,{},{},3,4,Na ...
- SSM-@Transactional 注释不生效
1.在applicationConext.xml 中配置事务注解驱动 <!-- 事务注解驱动 --> <tx:annotation-driven /> <!-- 配置事务 ...
- typescript的lambads解决this关键字找不到属性
var people = { name: ["abc", "jack", "pepter", "jim"], getna ...
- JavaScript控制流及关键字与C语言之比较
学习JavaScript控制流及关键字概念前,对有过C语言学习经验的同学来说,那么关键字,控制语句概念并不陌生.我们先来看看C语言吧: C语言的32个关键字和9种控制语句 9种控制语句: if.if- ...
- js 去掉字符串前后空格5种方法
第一种:循环检查替换 //供使用者调用 function trim(s){ return trimRight(trimLeft(s)); } //去掉左边的空白 function trimLeft(s ...
- Day7下
T1 我直接就用的LCA ,可能慢点.反正数据试过了. T2 期望dp不会啊. T3 好麻烦.