#include<iostream>#include<cstring>#include<algorithm>#include<cmath>#include<cstdlib>#include<climits>#include<stack>#include<vector>#include<queue>#include<set>#include<bitset>#include<map>//#include<regex>#include<cstdio>#include<iomanip>#pragma GCC optimize(2)#define up(i,a,b) for(int i=a;i<b;i++)#define dw(i,a,b) for(int i=a;i>b;i--)#define upd(i,a,b) for(int i=a;i<=b;i++)#define dwd(i,a,b) for(int i=a;i>=b;i--)//#define localtypedeflonglong ll;typedefunsignedlonglong ull;constdouble esp =1e-6;constdouble pi =acos(-1.0);constint INF =0x3f3f3f3f;constint inf =1e9;usingnamespace std;
ll read(){char ch =getchar(); ll x =0, f =1;while(ch<'0'|| ch>'9'){if(ch =='-')f =-1; ch =getchar();}while(ch >='0'&& ch <='9'){ x = x *10+ ch -'0'; ch =getchar();}return x * f;}typedef pair<int,int> pir;#define lson l,mid,root<<1#define rson mid+1,r,root<<1|1#define lrt root<<1#define rrt root<<1|1constint N =1e5+10;int T;int n, m;struct zxs {int ls[N *300];int rs[N *300];int tr[N *300];ll tr2[N *300];int root[N];int tot =0;vector<int>vecl, vecr;voidclear(){vecl.clear(); vecr.clear();tot =0;upd(i,0, N *290)ls[i]= rs[i]= tr[i]=0;upd(i,0, n)root[i]=0;}intlowbit(int i){return i &(-i);}voidmodify(int&o,int l,int r,int k,int val,int pos){if(!o)o =++tot;tr[o]+= val;tr2[o]+=1ll* val * pos;if(l == r)return;int mid =(l + r)>>1;if(k <= mid)modify(ls[o], l, mid, k, val, pos);elsemodify(rs[o], mid +1, r, k, val, pos);}voidpre_modify(int x,int k,int val){for(int i = x; i <= n; i +=lowbit(i))modify(root[i],1, n, k, val,i);}intquery(int l,int r,int k,int L,int R){if(l == r)return l;int mid =(l + r)>>1;int tsum =0;for(auto p : vecr){tsum +=1ll*(R +1)*tr[ls[p]]- tr2[ls[p]];}for(auto p : vecl){tsum -=1ll*(L +1)*tr[ls[p]]- tr2[ls[p]];}if(tsum >= k){for(int i =0; i < vecr.size(); i++)vecr[i]= ls[vecr[i]];for(int i =0; i < vecl.size(); i++)vecl[i]= ls[vecl[i]];returnquery(l, mid, k, L, R);}else{for(int i =0; i < vecr.size(); i++)vecr[i]= rs[vecr[i]];for(int i =0; i < vecl.size(); i++)vecl[i]= rs[vecl[i]];returnquery(mid +1, r, k - tsum, L, R);}}intpre_query(int l,int r,int k){vecl.clear(); vecr.clear();for(int i = r; i; i -=lowbit(i))vecr.push_back(root[i]);for(int i = l -1; i; i -=lowbit(i))vecl.push_back(root[i]);returnquery(1, n, k, l, r);}intquery_v(int l,int r,int k,int L,int R){int tsum =0;if(l == r){for(auto p : vecr)tsum +=1ll*(R +1)*tr[p]- tr2[p];for(auto p : vecl)tsum -=1ll*(L +1)*tr[p]- tr2[p];return tsum;}int mid =(l + r)>>1;if(mid >= k){for(int i =0; i < vecr.size(); i++)vecr[i]= ls[vecr[i]];for(int i =0; i < vecl.size(); i++)vecl[i]= ls[vecl[i]];returnquery_v(l, mid, k, L, R);}else{for(int i =0; i < vecr.size(); i++)vecr[i]= rs[vecr[i]];for(int i =0; i < vecl.size(); i++)vecl[i]= rs[vecl[i]];returnquery_v(mid +1, r, k, L, R);}}intpre_val(int l,int r,int k){vecl.clear(); vecr.clear();for(int i = r; i; i -=lowbit(i))vecr.push_back(root[i]);for(int i = l -1; i; i -=lowbit(i))vecl.push_back(root[i]);returnquery_v(1, n, k, l, r);}}TR;intmain(){T =read();while(T--){n =read(), m =read();TR.clear();int u;upd(i,1, n){u =read();TR.pre_modify(i, u,1);}int op, l, r, x, y;while(m--){op =read();if(op==1){l =read(), r =read(); x =read(), y =read();int vv = TR.pre_val(l, r, x);TR.pre_modify(l, x,-vv);TR.pre_modify(r +1, x, vv);TR.pre_modify(l, y, vv);TR.pre_modify(r +1, y,-vv);}else{l =read(), r =read(); x =read();printf("%d\n", TR.pre_query(l, r, x));}}}return0;}
后來發現分塊才是正解。 我是這樣想的,詢問第k大不用多說,修改的時候,先查找區間里面,x有多少個,然后區間修改,這里使用樹狀數組的修改方式,記錄 s u m [ i ] , i ? s u m [ i ] sum[i],i*sum[i] sum[i],i?sum[i]。 這樣的話查詢變成 ( p o s + 1 ) ? s u m [ i ] ? s u m [ i ] ? i (pos+1)*sum[i]-sum[i]*i (pos+1)?sum[i]?sum[i]?i即可。然而,發現MLE。空間完全承受不住,然后就GG了,用了一個多小時劃水。 然后配隊友開了H,兩個小時過了H。然后又去接著搞D。 最后一個小時寫的L。寫的時候一開始想用樹狀數組去解決,然后T了三發(真要吐了)。然后想了暴力求前綴的方式,去維護
題解: d p [ i ] [ j ] [ 0 ] dp[i][j][0] dp[i][j][0]表示以第i個結尾,另一個串以j結尾,長度為偶數的答案。 d p [ i ] [ j ] [ 1 ] dp[i][j][1] dp[i][j][1]表示以第i個結尾,另一個串以j結尾,長度為奇數的答案。 當且僅當 a [ i ] = = b [ j ] a[i]==b[j] a[i]==b[j]的時候,有轉移。 可以發現 d p [ i ] [ j ] [ 0 ] dp[i][j][0] dp[i][j][0]的轉移為他前面,所有 a [ k ] < a [ i ] a[k]<a[i] a[k]<a[i]并且 k < i k<i k<i轉移而來。 同理,奇數相反。故我們令 s u m [ j ] [ 0 ] , s u m [ j ] [ 1 ] sum[j][0],sum[j][1] sum[j][0],sum[j][1]表示 b [ j ] b[j] b[j]的所有偶數\奇數前綴和。當 a [ i ] < b [ j ] a[i]<b[j] a[i]<b[j]時,說明這個 b [ j ] b[j] b[j]可以作為偶數結尾( a [ i ] = = b [ j ] a[i]==b[j] a[i]==b[j])同理可以推奇數結尾。故我們就能在 o ( n ? m ) o(n*m) o(n?m)的時間內,維護出答案。 總結:自己太菜了
#include<iostream>#include<cstring>#include<algorithm>#include<cmath>#include<cstdlib>#include<climits>#include<stack>#include<vector>#include<queue>#include<set>#include<bitset>#include<map>//#include<regex>#include<cstdio>#include<iomanip>#pragma GCC optimize(2)#define up(i,a,b) for(int i=a;i<b;i++)#define dw(i,a,b) for(int i=a;i>b;i--)#define upd(i,a,b) for(int i=a;i<=b;i++)#define dwd(i,a,b) for(int i=a;i>=b;i--)//#define localtypedeflonglong ll;typedefunsignedlonglong ull;constdouble esp =1e-6;constdouble pi =acos(-1.0);constint INF =0x3f3f3f3f;constint inf =1e9;usingnamespace std;
ll read(){char ch =getchar(); ll x =0, f =1;while(ch<'0'|| ch>'9'){if(ch =='-')f =-1; ch =getchar();}while(ch >='0'&& ch <='9'){ x = x *10+ ch -'0'; ch =getchar();}return x * f;}typedef pair<int,int> pir;#define lson l,mid,root<<1#define rson mid+1,r,root<<1|1#define lrt root<<1#define rrt root<<1|1int T;constint N =2e3+10;constint mod =998244353;
ll a[N], b[N];int n, m;
ll dp[N][N][10];
ll sum[N][2];
vector<int>vec;int id[N];
ll add(ll a, ll b){return a + b >= mod ? a + b - mod : a + b;}intmain(){T =read();while(T--){n =read(), m =read();upd(i,0, n)upd(j,0, m)upd(k,0,1)dp[i][j][k]= sum[i][k]=0;upd(i,1, n)a[i]=read(), vec.push_back(a[i]);upd(i,1, m)b[i]=read();ll ans =0;upd(i,1, n){ll cnt0 =0, cnt1 =0;upd(j,1, m){if(a[i]== b[j]){ans =add(cnt1, ans);ans =add(cnt0 +1, ans);dp[i][j][0]=add(cnt1, dp[i][j][0]);dp[i][j][1]=add(cnt0 +1, dp[i][j][1]);}elseif(a[i]< b[j]){cnt0 =add(cnt0, sum[j][0]);}else{cnt1 =add(cnt1, sum[j][1]);}}upd(j,1, m){sum[j][0]=add(sum[j][0], dp[i][j][0]);sum[j][1]=add(sum[j][1], dp[i][j][1]);}}cout << ans << endl;}return0;}