思路:不知为啥,感觉这题很水,难度系数却标了2900,我们枚举a数组,判断ai是否能成为b[4k],用两个map存一下每个数出现次数,以及每个数最后出现的位置,如果 ai 出现了4次,那么直接把这四个数加进b数组,如果 ai 出现了大于1次且不合法(怎么判断合法后面讲),假设 p 是这个数上一次出现的位置,用线段树把区间[p + 1, i - 1]覆盖为ai,那么什么时候 ai 是合法的呢,我们先用线段树查询 p 点是否被覆盖,如果被覆盖,那么ai合法,并且把线段树清空,如果不合法,就把区间[ p + 1, i - 1]覆盖。
#include<bits/stdc++.h>
using namespace std;constint maxn =5e5+10;
map<int,int> mp, mp2;
queue<int> q;int a[maxn];int tree[maxn *4], tag[maxn *4];voidpushdown(int o,int ls,int rs){if(tag[o]!=-1){
tag[ls]= tag[rs]= tree[ls]= tree[rs]= tag[o];
tag[o]=-1;}}voidup(int o,int l,int r,int ql,int qr,int v){if(l >= ql && r <= qr){
tree[o]= v;
tag[o]= v;return;}int m =(l + r)/2, ls = o *2, rs = o *2+1;pushdown(o, ls, rs);if(ql <= m)up(ls, l, m, ql, qr, v);if(qr > m)up(rs, m +1, r, ql, qr, v);}intqu(int o,int l,int r,int k){if(l == r)return tree[o];int m =(l + r)/2, ls = o *2, rs = o *2+1;pushdown(o, ls, rs);if(k <= m)returnqu(ls, l, m, k);elsereturnqu(rs, m +1, r, k);}intmain(){int n;scanf("%d",&n);for(int i =1; i <= n; i++){scanf("%d",&a[i]);if(mp[a[i]]==3){for(int j =1; j <=4; j++)
q.push(a[i]);
mp.clear();
mp2.clear();}elseif(mp[a[i]]){int x =qu(1,1, n, mp2[a[i]]);if(x){
q.push(x);
q.push(a[i]);
q.push(x);
q.push(a[i]);
mp.clear();
mp2.clear();up(1,1, n,1, n,0);}else{
mp[a[i]]++;int cur = mp2[a[i]];if(cur < i -1)up(1,1, n, cur +1, i -1, a[i]);
mp2[a[i]]= i;}}else
mp[a[i]]++, mp2[a[i]]= i;}printf("%d\n", q.size());while(!q.empty())printf("%d ", q.front()), q.pop();}
Codeforces Round #267 (Div. 2) E. Alex and Complicated Task 线段树
E. Alex and Complicated Task题意:给一个长度为5e5的数组a,让你选择最长的子序列b,使得b的长度为4的倍数,且b[4k+1] = b[4k+3],b[4k+2] = b[4k+4]。思路:不知为啥,感觉这题很水,难度系数却标了2900,我们枚举a数组,判断ai是否能成为b[4k],用两个map存一下每个数出现次数,以及每个数最后出现的位置,如果 ai 出现了...