[HNOI2010]物品调度

看似很难

其实很水

仔细观察其实是两问。

第一问确定xi,yi,

posi=(ci+d*xi+yi) mod n不是白给的。

其实是同一个d*x+c的环上的所有点通过xi调整找到,yi的作用是更新到另一个环上去。

暴力枚举yi,每个环上用并查集维护紧跟着下一个可选择的

如果下一个被删除了,那么这个环已经用完,++yi

可以过。(因为数据水,zhoutb2333 dalao已经卡掉)

所以,考虑对环和环之间也用并查集维护一下,这样总的复杂度就是O(N)了

 

第二问更水

类似置换的问题做过很多次了。

找到置换环之后,由于必须和空位交换,所以含空位的len-1次,不含空位的len+1次(要把空位换进来多一次)

环与环之间交换是没有必要的。

 

一些值得注意的坑是:

对于这种取模的问题,ci,d上来直接对n取模了事。。

否则可能比n大,而并查集中未定义,或者直接RE

代码:(暴力枚举y)

#include<bits/stdc++.h>
#define reg register int
#define il inline
#define numb (ch^'0')
#define int long long
using namespace std;
typedef long long ll;
il void rd(int &x){
    char ch;x=0;bool fl=false;
    while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
    for(x=numb;isdigit(ch=getchar());x=x*10+numb);
    (fl==true)&&(x=-x);
}
namespace Miracle{
const int N=100000+5;
int n,t,s;
int pos[N];
int q,p,m,d;
int c[N];
int fa[N];
int fin(int x){
    return fa[x]==x?x:fa[x]=fin(fa[x]);
}
bool dele[N];
bool vis[N];
int len;
int kil;
void init(){
    for(reg i=0;i<n;++i) fa[i]=i;
    memset(dele,0,sizeof dele);
    memset(pos,0,sizeof pos);
    memset(vis,0,sizeof vis);
    int go=(s+d)%n;
    fa[s]=go;dele[s]=1;
    ++kil;
    len=0;
}
int query(int st){
    int k=fin(st);
//    cout<<" kk "<<st<<" "<<d<<" : "<<k<<" "<<dele[k]<<" "<<(k+d)%n<<" "<<fin((k+d)%n)<<endl;
    if(!dele[k]){
        int lp=fin((k+d)%n);
        if(lp!=k) fa[k]=lp;
        dele[k]=1;
        ++kil;
        return k;
    }
    return -1;
}

void dfs(int x){
    vis[x]=1;++len;
    if(!vis[pos[x]]) dfs(pos[x]);
}
int main(){
    rd(t);
    while(t--){
        rd(n);rd(s);rd(q);rd(p);rd(m);rd(d);
        d%=n;
        init();
        c[0]=0;
        for(reg i=1;i<n;++i) c[i]=((ll)c[i-1]*q+p)%m;
        for(reg i=1;i<n;++i){
            c[i]%=n;
        //    cout<<" ii "<<i<<" "<<kil<<" "<<c[i]<<endl;
            int y=0;
            int tmp=0;
            while((tmp=query((c[i]+y)%n))==-1){
                ++y;
                //cout<<tmp<<" "<<y<<endl;
            }
            pos[i]=tmp;
        }
        pos[0]=s;
        int ans=0;
        for(reg i=0;i<n;++i){
            //cout<<pos[i]<<" ";
            if(!vis[i]) {
                len=0;
                if(pos[i]!=i){
                    dfs(i);
                    //cout<<" len "<<len<<endl;
                    if(i==0) ans+=len-1;
                    else ans+=len+1;
                }
            }
        }//cout<<endl;
        printf("%lld\n",ans);
    }
    return 0;
}

}
signed main(){
    Miracle::main();
    return 0;
}

/*
   Author: *Miracle*
   Date: 2018/12/27 14:17:54
*/
View Code

 

转载于:https://www.cnblogs.com/Miracevin/p/10185229.html

根据引用\[1\]和引用\[2\]的描述,题目中的影魔拥有n个灵魂,每个灵魂有一个战斗力ki。对于任意一对灵魂对i,j (i<j),如果不存在ks (i<s<j)大于ki或者kj,则会为影魔提供p1的攻击力。另一种情况是,如果存在一个位置k,满足ki<c<kj或者kj<c<ki,则会为影魔提供p2的攻击力。其他情况下的灵魂对不会为影魔提供攻击力。 根据引用\[3\]的描述,我们可以从左到右进行枚举。对于情况1,当扫到r\[i\]时,更新l\[i\]的贡献。对于情况2.1,当扫到l\[i\]时,更新区间\[i+1,r\[i\]-1\]的贡献。对于情况2.2,当扫到r\[i\]时,更新区间\[l\[i\]+1,i-1\]的贡献。 因此,对于给定的区间\[l,r\],我们可以根据上述方法计算出区间内所有下标二元组i,j (l<=i<j<=r)的贡献之和。 #### 引用[.reference_title] - *1* *3* [P3722 [AH2017/HNOI2017]影魔(树状数组)](https://blog.csdn.net/li_wen_zhuo/article/details/115446022)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [洛谷3722 AH2017/HNOI2017 影魔 线段树 单调栈](https://blog.csdn.net/forever_shi/article/details/119649910)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值