日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

CodeForces - 731D 80-th Level Archeology(线段树+暴力/差分)

發布時間:2024/4/11 编程问答 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 CodeForces - 731D 80-th Level Archeology(线段树+暴力/差分) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目鏈接:點擊查看

題目大意:給出 n 個數列,再給出一個模數 mod,每次操作可以將所有的數字進行:x = x %mod + 1 操作,問至少進行多少次操作,才能使得 n 個數列按照字典序非降序排列

題目分析:思維不夠暴力來湊。。感覺很像是威海線段樹維護哈希暴力取模的那個題,事實證明是可以類比過去的

先說我的思路,對于任意兩個相鄰的數列來說,先找出其首個不相同的位置 pos,然后記錄一下其值,在代碼中我記做了 a 和 b,因為對于這兩個數列來說,a 和 b 的大小關系就直接決定了這兩個數列的相對大小關系,所以只需要關注這里即可

然后用線段樹維護一下這最多 n - 1 個大小關系,也就是每個節點維護一下每個關系中 b - a 的值,因為我們想要使得 n 個數按照字典序非降序排列,也就是所有的 a <= b ,也就是 b - a >= 0,此時我們就可以暴力枚舉更新次數,每次將所有的 a 和 b 都加一,此時考慮三種情況:

  • 如果 a > b,且 a == mod,那么在一次更新后,a = 1,且 b - a 的值會發生改變
  • 如果 b > a,且 b == mod,那么在一次更新后,b = 1,且 b - a 的值會發生改變
  • 否則 b - a 的值不變
  • 不難看出每個關系中的 a 和 b 至多更新一次,因為暴力枚舉更新次數的話只需要枚舉 [ 0 , mod - 1 ] 就足夠了,所以對于每個位置維護一個變量?mmin 用來記錄當前節點還剩幾次 “加一操作” 后才需要更新即可,這樣均攤時間復雜度是 O( nlogn ) 的

    然后去網上看了題解,發現果然有簡單做法,那就是更需要思維的差分

    依然是借助上文中的 a 和 b 繼續講,對于一對相對大小關系 ( a , b ) 來說,仍然是分兩種情況討論一下:

  • a > b:更新次數 x 在 [ mod - a + 1 , mod - b?] 內是合法的,也就是滿足了 ( x + a )%mod + 1 < ( x + b )%mod + 1
  • b > a:同上,更新次數在 [ 0 , mod - b?] 和 [ mod - a + 1 , mod ] 內是合法的
  • 沒有沖突,比如 123 和 1234,永遠是 "123" < "1234":執行任意次操作都符合條件,即 [ 0 , mod ] 內都是可行的
  • 所以我們只需要找到某一個更新次數 i ,使得此時差分數組的前綴和等于 n - 1 就好了

    代碼:

    線段樹+暴力

    //#pragma GCC optimize(2) //#pragma GCC optimize("Ofast","inline","-ffast-math") //#pragma GCC target("avx,sse2,sse3,sse4,mmx") #include<iostream> #include<cstdio> #include<string> #include<ctime> #include<cmath> #include<cstring> #include<algorithm> #include<stack> #include<climits> #include<queue> #include<map> #include<set> #include<sstream> #include<cassert> #include<bitset> using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=1e6+100;int n,m;vector<int>a[N];vector<pair<int,int>>node;struct Node {int l,r;int mmin;//最小更新時間int delta;//b-aint a,b;int lazy;//最小更新時間的lazy }tree[N<<2];void pushup(int k) {tree[k].mmin=min(tree[k<<1].mmin,tree[k<<1|1].mmin);tree[k].delta=min(tree[k<<1].delta,tree[k<<1|1].delta); }void pushdown(int k) {if(tree[k].lazy){int lz=tree[k].lazy;tree[k].lazy=0;tree[k<<1].lazy+=lz;tree[k<<1|1].lazy+=lz;tree[k<<1].mmin+=lz;tree[k<<1|1].mmin+=lz;} }void build(int k,int l,int r) {tree[k].l=l;tree[k].r=r;tree[k].lazy=0;if(l==r){int a,b;tie(a,b)=node[l-1];tree[k].mmin=min(m-a+1,m-b+1);tree[k].delta=b-a;tree[k].a=a;tree[k].b=b;return;}int mid=l+r>>1;build(k<<1,l,mid);build(k<<1|1,mid+1,r);pushup(k); }void update() {tree[1].mmin--;tree[1].lazy--; }void update(int k) {if(tree[k].mmin>0)return;if(tree[k].l==tree[k].r){if(tree[k].a>tree[k].b){tree[k].b+=m-tree[k].a+1;tree[k].a=1;tree[k].delta=tree[k].b-tree[k].a;tree[k].mmin=m-tree[k].b+1;}else{tree[k].a+=m-tree[k].b+1;tree[k].b=1;tree[k].delta=tree[k].b-tree[k].a;tree[k].mmin=m-tree[k].a+1;}return;}pushdown(k);update(k<<1);update(k<<1|1);pushup(k); }int main() { #ifndef ONLINE_JUDGE // freopen("data.in.txt","r",stdin); // freopen("data.out.txt","w",stdout); #endif // ios::sync_with_stdio(false);scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){int num;scanf("%d",&num);for(int j=1;j<=num;j++){int x;scanf("%d",&x);a[i].push_back(x);}}for(int i=2;i<=n;i++)//查找相鄰兩個數列中的a和b{bool flag=(a[i-1].size()>a[i].size());for(int j=0;j<min(a[i].size(),a[i-1].size());j++){if(a[i][j]==a[i-1][j])continue;node.push_back(make_pair(a[i-1][j],a[i][j]));flag=false;break;}if(flag)//特判1234和123的情況return 0*puts("-1");}if(node.empty())//沒有沖突,無需更改return 0*puts("0");build(1,1,node.size());for(int i=0;i<=m;i++){if(tree[1].delta>0)return 0*printf("%d\n",i);update();update(1);}puts("-1");return 0; }

    差分:

    //#pragma GCC optimize(2) //#pragma GCC optimize("Ofast","inline","-ffast-math") //#pragma GCC target("avx,sse2,sse3,sse4,mmx") #include<iostream> #include<cstdio> #include<string> #include<ctime> #include<cmath> #include<cstring> #include<algorithm> #include<stack> #include<climits> #include<queue> #include<map> #include<set> #include<sstream> #include<cassert> #include<bitset> using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=1e6+100;vector<int>a[N];int delta[N];int main() { #ifndef ONLINE_JUDGE // freopen("data.in.txt","r",stdin); // freopen("data.out.txt","w",stdout); #endif // ios::sync_with_stdio(false);int n,m;scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){int num;scanf("%d",&num);for(int j=1;j<=num;j++){int x;scanf("%d",&x);a[i].push_back(x);}}for(int i=2;i<=n;i++)//查找相鄰兩個數列中的a和b{bool flag=true;for(int j=0;j<min(a[i].size(),a[i-1].size());j++){if(a[i][j]==a[i-1][j])continue;int x=a[i-1][j],y=a[i][j];if(x>y){delta[m-x+1]++;delta[m-y+1]--;}else{delta[0]++;delta[m-y+1]--;delta[m-x+1]++;delta[m]--;}flag=false;break;}if(flag){if(a[i-1].size()>a[i].size())//特判1234和123的情況return 0*puts("-1");else//特判123和1234的情況{delta[0]++;delta[m]--;}}}int sum=0;for(int i=0;i<m;i++){sum+=delta[i];if(sum==n-1)return 0*printf("%d\n",i);}puts("-1");return 0; }

    ?

    總結

    以上是生活随笔為你收集整理的CodeForces - 731D 80-th Level Archeology(线段树+暴力/差分)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。