ZOJ Monthly, January 2019 I Little Sub and Isomorphism Sequences(set 妙用) ZOJ4089
写这篇博客来证明自己的愚蠢 。。。Orz
题意:给定你个数组,以及一些单点修改,以及询问,每次询问需要求得,最长的字串长度,它在其他位置存在同构
题解:经过一些奇思妙想后 ,你可以发现问题是传化为了查询一个最大的区间这个区间的开头和结尾是相同的 ;
所以如果我们知道了某个数的最小位置与最大位置 , 我们是不是就可以很快的知道这个答案了 , 那问题又会来了 , 我怎样得到这个最早和最晚呢 ? 这里相当的疯狂 , 开了20W的set , 没错就是set , 其本身也是排了序的 , 所以我们将某数的所有的位置都放入到对应的set , 我们是不是就可以很快的查找与删除了;
但是题目给出的数据有10^9 , 我们是不是需要离散化 , 可是又带有修改 , 那我们是不是参考离线的打法 , 先将所以需要用的的数字存下来 , 离散化呀 ;
那问题又来拉 , 我怎么可以很快的得到最大的区间 , 我看到网上是有用线段树的Orz , 我是不会拉 , 所以我用了set.. 没有看错 ,就是set , 不过这个set 是一个结构体set ,里面记录的是某个数与这个数字对应的区间长度 , 为什么没有想到优先队列呢 , 很显然修改是会改变对应数的对应区间最大值 ,所以我们得用利于修改的数据结构 ,于是。。。。这题就set。。。
然后!!!我DUG了一晚 , 原来set 的删除并不是单纯的删除某数 , 比如你要删除X , 你要这样打 ,G.erase(G.find(X)); 卧槽。。我直接G..erase(X) 被自己蠢哭。。。还要注意删除前要判断容器里面是否有这样数,没有就不可以删除,这些是血的教训,希望我以后可以记得。Orz
#include<bits/stdc++.h> using namespace std ; #define N 200001 set<int> ST[N]; int a[N],b[N],n,m; int Len; struct no { int op , x, y; }q[N]; struct NO { int id; int val; bool operator < (const NO &a) const { return a.val<val; } }M,MM; multiset<NO>G; multiset<NO>::iterator it; void Hash() { sort(b+1,b+1+Len); Len=unique(b+1,b+1+Len)-b-1; for(int i=1 ; i<=n ; i++) a[i]=lower_bound(b+1,b+1+Len,a[i])-b; for(int i=1 ; i<=m ; i++) { if(q[i].op==1) { q[i].y=lower_bound(b+1,b+1+Len,q[i].y)-b; } } } int main() { int t; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); for(int i=1 ; i<=n+m ; i++ ) ST[i].clear(); Len=0;G.clear(); memset(q,0,sizeof(q)); for(int i=1 ; i<=n ; i++) { scanf("%d",&a[i]); b[++Len]=a[i];///离散化 } for(int i=1 ; i<=m ; i++) { int op,x,y; scanf("%d",&op); if(op==1) { scanf("%d%d",&x,&y); q[i].op=op ; q[i].x=x ; q[i].y=y; b[++Len]=y; } } Hash(); for(int i=1 ; i<=n ; i++) ST[a[i]].insert(i); for(int i=1 ; i<=n+m ; i++) { if(ST[i].size()>=2) { M.id=i; M.val=(*ST[i].rbegin())-(*ST[i].begin()); G.insert(M); } } for(int i=1 ; i<=m ; i++) { if(q[i].op==1) { int v = a[q[i].x] , X=q[i].x , Y=q[i].y; int LEN=(*ST[v].rbegin())-(*ST[v].begin()); M.id=v; M.val=LEN; if(ST[v].find(X)!=ST[v].end()) ST[v].erase(ST[v].find(X)); if(G.find(M)!=G.end()) G.erase(G.find(M)); if(ST[v].size()>=2) { M.val=(*ST[v].rbegin())-(*ST[v].begin()); G.insert(M); } a[X]=Y; v=Y; if(ST[v].size()>=2) { M.id=v; M.val=(*ST[v].rbegin())-(*ST[v].begin()); G.erase(G.find(M)); } ST[v].insert(X); if(ST[v].size()>=2) { M.id=v ; M.val=(*ST[v].rbegin())-(*ST[v].begin()); G.insert(M); } } else { if(G.empty()) puts("-1"); else { M=(*G.begin()); if((M.val)==0) puts("-1"); else printf("%d\n",(M.val)); } } /* printf("%d\n",i); for(it=G.begin() ; it!=G.end() ; it++) { MM=*it; printf("%d %d\n",MM.id,MM.val); }*/ } } return 0; }