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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

csps-s模拟测试62,63Graph,Permutation,Tree,Game题解

發(fā)布時(shí)間:2024/8/26 综合教程 30 生活家
生活随笔 收集整理的這篇文章主要介紹了 csps-s模拟测试62,63Graph,Permutation,Tree,Game题解 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

題面:https://www.cnblogs.com/Juve/articles/11631298.html

permutation:

參考:https://www.cnblogs.com/clno1/p/10832579.html

因?yàn)樵瓉淼臄?shù)組不好做于是我們想反過來數(shù)組,根據(jù)交換條件:值相鄰且位置差大于等于k,那么在變換后的數(shù)組就變成了位置相鄰且差值大于等于k。這樣的話變換操作變成了,相鄰的大于等于k的值臨近交換,于是我們注意到因?yàn)楝F(xiàn)在只能臨近交換的原因,兩個(gè)差值小于k的數(shù)他們的相對位置不可能發(fā)生改變。那么問題就變成了,在只有一些相對位置限制條件下,無限制的可以隨意交換位置,求這個(gè)數(shù)組的最小字典序(原數(shù)組字典序最小也是現(xiàn)在數(shù)組字典序最小)。那么我們?nèi)菀紫氲酵負(fù)渑判颉?/p>

但是如果每個(gè)點(diǎn)都想后面差值小于k的點(diǎn)連邊的話,這個(gè)圖會變得十分巨大,時(shí)間無法承受。于是我們必循得考慮優(yōu)化建圖:我們注意到像a->b,b->c,a->c這種建圖,a->c這條邊是不必要的。于是我們想辦法避免掉這種無意義的邊,所以對于某個(gè)點(diǎn),我們讓它向后面的所有限制(即差值小于k)中只向最小的那一個(gè)點(diǎn)連邊,那么用線段樹維護(hù)這樣的信息,這樣就達(dá)到優(yōu)化建圖的目的。

這樣只向最小的連邊為什么是對的呢?借用上面大佬的一句話:倒著加入,顯然p_i 連向 (p_i-k, p_i)∪(p_i, p_i+k)。我們只需要分別連向兩個(gè)區(qū)間中下標(biāo)最小的那一個(gè)即可。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<vector>
 6 #include<queue>
 7 using namespace std;
 8 const int MAXN=5e5+5;
 9 int n,k,a[MAXN],pos[MAXN],du[MAXN],ans[MAXN],num=0;
10 vector<int>m[MAXN];
11 priority_queue<int>q;
12 int tr[MAXN<<2];
13 void update(int k,int l,int r,int opt,int val){
14     if(l==r){
15         tr[k]=min(tr[k],val);
16         return ;
17     }
18     int mid=(l+r)>>1;
19     if(opt<=mid) update(k<<1,l,mid,opt,val);
20     else update(k<<1|1,mid+1,r,opt,val);
21     tr[k]=min(tr[k<<1],tr[k<<1|1]);
22 }
23 int query(int k,int l,int r,int opl,int opr){
24     if(opl>opr) return 0x3f3f3f3f;
25     if(opl<=l&&r<=opr) return tr[k];
26     int mid=(l+r)>>1,res=0x3f3f3f3f;
27     if(opl<=mid) res=min(res,query(k<<1,l,mid,opl,opr));
28     if(opr>mid) res=min(res,query(k<<1|1,mid+1,r,opl,opr));
29     return res;
30 }
31 int main(){
32     scanf("%d%d",&n,&k);
33     for(int i=1;i<=n;++i){
34         scanf("%d",&a[i]);
35         pos[a[i]]=i;
36     }
37     memset(tr,0x3f,sizeof(tr));
38     for(int i=n;i>=1;--i){
39         int p=query(1,1,n,max(1,pos[i]-k+1),pos[i]);
40         if(p<=n) m[pos[i]].push_back(pos[p]),++du[pos[p]];
41         p=query(1,1,n,pos[i],min(n,pos[i]+k-1));
42         if(p<=n) m[pos[i]].push_back(pos[p]),++du[pos[p]];
43         update(1,1,n,pos[i],i);
44     }
45     for(int i=1;i<=n;++i){
46         if(!du[i]) q.push(-i);
47     }
48     while(!q.empty()){
49         int x=-q.top();
50         q.pop();
51         ans[x]=++num;
52         int N=m[x].size();
53         for(int i=0;i<N;++i){
54             int y=m[x][i];
55             --du[y];
56             if(!du[y]) q.push(-y);
57         }
58     }
59     for(int i=1;i<=n;++i){
60         printf("%d
",ans[i]);
61     }
62     return 0;
63 }

View Code

tree:

好像是個(gè)結(jié)論:邊權(quán)之和就是答案

#include<cstdio>
#define int long long
int n,ans=0;
signed main(){
    scanf("%lld",&n);
    for(int i=1,u,v,w;i<n;++i){
        scanf("%lld%lld%lld",&u,&v,&w);
        ans+=w;
    }
    printf("%lld
",ans);
    return 0;
}

View Code

game:

模擬用堆可以有50分

考慮如何優(yōu)化

我們對于前p個(gè)數(shù)找出最大值,并開桶統(tǒng)計(jì)所有數(shù)出現(xiàn)的次數(shù)

然后對于一個(gè)新加入的點(diǎn),如果它大于當(dāng)前的最大值,那么下一個(gè)人一定選擇新加如的這個(gè)點(diǎn),所以最大值沒有變

否則更新新加入的數(shù)的次數(shù)并更新最大值

考慮到最大值一定不上升,所以復(fù)雜度較有保障

但是還是會T,所以我們離散化一下

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<unordered_map>
#define re register
using namespace std;
const int MAXN=100005;
int n,k,a[MAXN],p,tim[MAXN],cnt,b[MAXN];
signed main(){
    scanf("%d%d",&n,&k);
    for(re int i=1;i<=n;++i) scanf("%d",&a[i]),b[i]=a[i];
    sort(b+1,b+n+1);
    cnt=unique(b+1,b+n+1)-b-1;
    for(int i=1;i<=n;++i) a[i]=lower_bound(b+1,b+cnt+1,a[i])-b;
    while(k--){
        scanf("%d",&p);
        re long long ans1=0,ans2=0;
        re int maxp=0;
        for(re int i=1;i<=p;++i){
            ++tim[a[i]];
            maxp=max(maxp,a[i]);
        }
        ans1+=b[maxp];
        --tim[maxp];
        while(maxp>0&&tim[maxp]==0) --maxp;
        for(re int i=2;i<=n;++i){
            if(i&1){
                if(p+1<=n){
                    ++p;
                    if(a[p]>=maxp) ans1+=b[a[p]];
                    else{
                        ans1+=b[maxp];
                        --tim[maxp];
                        ++tim[a[p]];
                        while(maxp>0&&tim[maxp]==0) --maxp;
                    }
                }else{
                    ans1+=b[maxp];
                    --tim[maxp];
                    while(maxp>0&&tim[maxp]==0) --maxp;
                }
            }else{
                if(p+1<=n){
                    ++p;
                    if(a[p]>=maxp) ans2+=b[a[p]];
                    else{
                        ans2+=b[maxp];
                        --tim[maxp];
                        ++tim[a[p]];
                        while(maxp>0&&tim[maxp]==0) --maxp;
                    }
                }else{
                    ans2+=b[maxp];
                    --tim[maxp];
                    while(maxp>0&&tim[maxp]==0) --maxp;
                }
            }
        }
        printf("%lld
",ans1-ans2);
    }
    return 0;
}

View Code

總結(jié)

以上是生活随笔為你收集整理的csps-s模拟测试62,63Graph,Permutation,Tree,Game题解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。