首页 > 其他分享 >CSP-S模拟8 选举 港口设施 幽深府邸 长途巴士

CSP-S模拟8 选举 港口设施 幽深府邸 长途巴士

时间:2022-09-21 22:03:50浏览次数:79  
标签:ch int top long 府邸 st 巴士 CSP define

DP和贪心的完美结合。

T1:n个州,你要从中选出K个进行演讲,每个州有键值(a,b),代表获得选票需要a时间,得到助理人需要b时间,a<=b。得到助理人之后可以同时演讲,演讲时间可以累加。问最少演讲时间。n<=500.

结论:
(1)假设选择若干个协助州,按照b排序的潜在协助州前缀一定不存在反对州
(2)如果要选择b=-1的州x个,一定按照a升序选前x小
(3)先选协助州,再选支持州
(4)m个人同时在一个州演讲,比分散不劣
所以设\(dp[i][j]表示前i个州选择j个协助州的最小时间(i<=min(K,helpstate))\)把州先按照b排序,-1都放后边,我们先枚举选择多少个协助州,假设b个,再进行dp,因为这样对于支持州我们可以直接算出它的花费,潜在协助州也可能成为支持州(a<<b)。求出dp[1K][b]后,我们枚举第一维位置,代表前1i个交杂支持和协助,剩下n-i个是全部支持,花费是a/(b+1)。预处理g[x][y]:x~n选协助州的前y小。\(O(K^2*n)\)

点击查看代码


#include<bits/stdc++.h>
using namespace std;
#define _f(i,a,b) for(register int i=a;i<=b;++i)
#define f_(i,a,b) for(register int i=a;i>=b;--i)
#define chu printf
#define ll long long
#define rint register int
#define ull unsigned long long
inline ll re()
{
    ll x=0,h=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')h=-1;
        ch=getchar();
    }
    while(ch<='9'&&ch>='0')
    {
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*h;
}
const int N=0;
double f[510][510];
int g[510][510];
int n,K,bj;
struct node
{
    int a,b;
}e[510],tmp[510];
bool cmp(node&A,node&B)
{
    return A.a<B.a;
}
bool cmp2(node&A,node&B)
{
    return A.b<B.b;
}
int main()
{
  // freopen("1.in","r",stdin);
   //freopen("a.out","w",stdout);
   n=re(),K=re();
   _f(i,1,n)
   {
       e[i].a=re(),e[i].b=re();
       if(e[i].b==-1)e[i].b=1e9;
   }
   sort(e+1,e+1+n,cmp2);
   int bj=-1;
   _f(i,1,n)
   if(bj==-1&&e[i].b==1000000000)bj=i;
   if(bj==-1)bj=n+1;//第一个不是协作州的地方
    _f(i,1,n)
    {
        _f(j,1,n)tmp[j]=e[j];
        sort(tmp+i,tmp+n+1,cmp);
        _f(j,i,n)
        g[i][j-i+1]=tmp[j].a+g[i][j-i];
    }
   // _f(i,1,n)
  //  _f(j,1,n)
   // chu("g[%d][%d]:%d\n",i,j,g[i][j]);
    int bianjie=min(K,bj-1);//找多少协作州,最多的
    double minans=1e9;
    //chu("bianjie:%d\n",bianjie);
    _f(b,0,min(K-1,bj-1))//找多少协作州
    {
        _f(i,0,bianjie)
        _f(j,0,b)
        f[i][j]=1e9;
        f[0][0]=0;
        _f(i,1,bianjie)//考虑前多少个州(选的)
        {
            f[i][0]=f[i-1][0]+(double)e[i].a/(b+1);//不当做协作州
            _f(j,1,min(b,i))//有几个协作州
            {
                f[i][j]=min(f[i-1][j]+(double)e[i].a/(b+1),f[i-1][j-1]+(double)e[i].b/(j));
            }
        }
        _f(i,b,bianjie)//考虑前多少个里面找协作州
        {
           // chu("(%d %d)%lf+%lf\n",i,b,f[i][b],(double)g[i+1][K-i]/(b+1));
            minans=min(minans,f[i][b]+(double)g[i+1][K-i]/(b+1));
        }
       // chu("rod:%d  mians:%lf\n",b,minans);
    }
    chu("%.15lf",minans);
    return 0;
}
/*
3
3
1 5
2 3
4 5
*/

T2:给你2个栈,n个元素的入栈出栈次序,求元素属于栈的方案数。(n<=1e6)

发现如果([)]一定不能放一起,有矛盾关系,并查集维护,最后答案就是$2 ^ \(联通快个数。找块\)O(n^2)$。考虑优化,只枚举对于一个右边界xl,在[xl,xr]区间第一次出现的元素,连边O(E),nxt[x]表示入栈次序是x的元素下一个最远存在矛盾关系的位置,搞一个并查集维护对于pos位置,pos以及之后到当前遍历的满足右端点没有出现的位置(get父亲)。这样你在遍历[xl,xr]区间,每次跳getfa(nxt[x]+1),然后维护j=cnt_now(交叉最远),j一定就是具有矛盾关系的。注意先把fa[x]=getfa(x+1)一下,就可以了。

点击查看代码




#include<bits/stdc++.h>
using namespace std;
#define _f(i,a,b) for(register int i=a;i<=b;++i)
#define f_(i,a,b) for(register int i=a;i>=b;--i)
#define chu printf
#define ll long long
#define rint register int
#define ull unsigned long long
inline ll re()
{
    ll x=0,h=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')h=-1;
        ch=getchar();
    }
    while(ch<='9'&&ch>='0')
    {
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*h;
}
const int N=1e6+10;const int mod=1e9+7;
vector<int>e[N];
int col[N];
int nxt[N],fa[N],le[N],id[N<<1],a[N],cnt;
int n;
ll ans=1;
void qm(int a,int b)
{
    while(b)
    {
        if(b&1)ans=(ll)ans*a%mod;
        b>>=1;
        a=(ll)a*a%mod;
    }
}
inline int find(int x)
{
    return fa[x]==x?x:fa[x]=find(fa[x]);
}
inline void addedge(int u,int v)
{
    e[u].push_back(v);e[v].push_back(u);
}
inline int dfs(int u)
{
    for(int i=0;i<e[u].size();++i)
    {
        int v=e[u][i];
        if(col[v]!=0&&col[v]==col[u])return 0;
        if(col[v]==0)
        {
            col[v]=-col[u];
            if(!dfs(v))return 0;
        }
    }
    return 1;
}
int main()
{
  // freopen("1.in","r",stdin);
   //freopen("a.out","w",stdout);
   int l,r;
   n=re();
   _f(i,1,n)
   {
       int l=re(),r=re();
       id[l]=id[r]=i;
   }
   _f(i,1,n)nxt[i]=i,fa[i]=i;
   fa[n+1]=n+1;
   _f(i,1,n<<1)
   {
       int p=id[i];
       if(!le[p])a[++cnt]=p,le[p]=cnt;
       else
       {
           int u=le[p];
           fa[u]=find(u+1);
           for(int j=fa[u],k;j<=cnt;j=k)
           {
               addedge(a[j],p);k=find(nxt[j]+1);nxt[j]=cnt;
           }
       }
   }
   int cnt=0;
   memset(col,0,sizeof(col));
   _f(i,1,n)
   {
       if(col[i]==0)
       {
           col[i]=1;if(dfs(i))++cnt;
           else
           {
               chu("0");return 0;
           }
       }
   }
   qm(2,cnt);
   chu("%lld",ans);
    return 0;
}
/*
7
4
4 -1
11 -1
6 -1
12 -1
36 -1
11 -1
20 -1

4 4
3 3
4 4 
6 6 
7 7 
*/

T3:一个一维房间,从i-->i+1需要钥匙c[i],每个房间有Bi把钥匙,互不相同,你可以捡钥匙q组询问,(x,y),问从x到y行不行。(q,n<=5e5)

L[]R[]维护向左向右最多到的位置,r[x]维护如果要向左,向右第一个出现c(i-1)的位置.先从左边扫一下R[x],然后倒着扫一遍L,同时更新R,这样每次跳的区段就很大,会比较快。
至于O(n)的...

点击查看代码


#include <bits/stdc++.h>
using namespace std;
const int N=500010;
vector<int> key[N];
int n,q,c[N],l[N],r[N],L[N],R[N],num[N],la[N];
int main(){
	scanf("%d",&n);
	for (int i=1; i<n; ++i) scanf("%d",&c[i]);
	//cerr<<"END"<<endl;
	for (int i=1; i<=n; ++i){
		scanf("%d",&num[i]);
		for (int j=1; j<=num[i]; ++j){
			int x; scanf("%d",&x);
			key[i].emplace_back(x);
		}
	}
	//cerr<<"END2";
	for (int i=1; i<=n; ++i){
		for (auto j:key[i])
			la[j]=i;
		l[i]=la[c[i]];
	}
	for (int i=1; i<=n; ++i) la[i]=n+1;
	for (int i=n; i>=1; --i){
		for (auto j:key[i])
			la[j]=i;
		r[i]=la[c[i-1]];
	}
	R[n]=n;
	for (int i=n-1; i>=1; --i){
		if (l[i]<i){
			R[i]=i;
			continue;
		}
		R[i]=R[i+1];
		while (R[i]<n&&l[R[i]]>=i) R[i]=R[R[i]+1];
	}
	//for (int i=1; i<=n; ++i) cerr<<i<<" "<<R[i]<<endl;
	//return 0;
	L[1]=1;
	for (int i=2; i<=n; ++i){
		if (r[i]>R[i]){
			L[i]=i;
			continue;
		}
		if (R[i-1]>=i){
			L[i]=L[i-1];
			R[i]=R[i-1];
			continue;
		}
		L[i]=L[i-1];
		while (1){
			bool fl=0;
			if (L[i]>1&&r[L[i]]<=R[i]){
				fl=1;
				L[i]=L[L[i]-1];
			}
			if (R[i]<n&&l[R[i]]>=L[i]){
				fl=1;
				R[i]=R[R[i]+1];
			}
			if (!fl) break;
		}
		//cerr<<i<<" "<<L[i]<<" "<<R[i]<<endl;
		//return 0;
	}
	//for (int i=1; i<=n; ++i) cerr<<L[i]<<" "<<R[i]<<endl;
	//cerr<<"UP";
	scanf("%d",&q);
	//cerr<<"FUCK";
	for (int i=1; i<=q; ++i){
		int x,y; scanf("%d%d",&x,&y);
		cout<<(L[x]<=y&&y<=R[x]?"YES\n":"NO\n");
	}
}

T4:贪心+DP+斜率优化

https://www.cnblogs.com/Itst/p/10623598.html
注意因为Min不单调,所以不能删除队尾,需要二分斜率,[L,R),mid-1一定存在,边界考虑一下。

点击查看代码


#include<bits/stdc++.h>
using namespace std;
#define _f(i,a,b) for(register int i=a;i<=b;++i)
#define f_(i,a,b) for(register int i=a;i>=b;--i)
#define chu printf
#define ll long long
#define rint register int
#define ull unsigned long long
inline ll re()
{
    ll x=0,h=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')h=-1;
        ch=getchar();
    }
    while(ch<='9'&&ch>='0')
    {
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*h;
}
const int N=2e5+100;
#define int ll
int X,n,m,W,T;
int s[N],st[N],pre[N],f[N],top;//休息点
struct Node
{
    int D,C,Min;
    inline bool operator<(const Node&U)const
    {
        return D<U.D;//按照取水次序
    }
}ps[N];
pair<int,int>t[N];
#define S(x)  (f[x]-pre[x])
inline void insert(int x)
{
    while(top>1&&(S(st[top])-S(st[top-1]))*(x-st[top])>=(S(x)-S(st[top]))*(st[top]-st[top-1]))--top;
    st[++top]=x;
    //(S(st[top])-S(st[top-1]))*(x-st[top])>=(S(x)-S(st[top]))*(st[top]-st[top-1])
}
inline int getans(int x)
{
    int l=1,r=top+1;
    while(r-l>1)//[l,r),mid-1一定存在
    {
        int mid=(l+r)>>1;
        if(S(st[mid])-S(st[mid-1])<=x*(st[mid]-st[mid-1]))l=mid;
        else r=mid;
    }
    return st[l];
}
signed main()
{
  // freopen("1.in","r",stdin);
   //freopen("a.out","w",stdout);
   X=re(),n=re(),m=re(),W=re(),T=re();
    _f(i,1,n)
    {
        s[i]=re();t[i]=make_pair(s[i]%T,s[i]);
    }
    _f(i,1,m)
    {
        ps[i].D=re()%T;ps[i].C=re();
    }
    t[n+1]=make_pair(X%T,X);
    sort(t+1,t+2+n);int p=1;
    sort(ps+1,ps+1+m);
    ps[m+1].D=X+1;
    _f(i,1,m)//给每个乘客找
    {
        //Di<s%T<D(i+1)
        ps[i].Min=1e17;
        while(p<=n+1&&t[p].first<ps[i].D)++p;
        while(p<=n+1&&t[p].first<ps[i+1].D)
        {
            ps[i].Min=min(ps[i].Min,t[p].second/T);
            ++p;
        }
        pre[i]=pre[i-1]+ps[i].C;
    }
    ++top;//有一个空
    //Min处理好了
    memset(f,0x3f,sizeof(f));
    f[0]=0;//考虑前i个乘客的最小花费
    _f(i,1,m)
    {
        f[i]=f[i-1]+((X-ps[i].D)/T+1)*W;
        if(ps[i].Min!=(ll)1e17)
        {
            int j=getans(W*ps[i].Min);
            f[i]=min(f[i],f[j]+pre[i]-pre[j]+W*(i-j)*ps[i].Min);
        }
        insert(i);
    }
    chu("%lld",f[m]+(X/T+1)*W);
    return 0;
}
/*
*/

标签:ch,int,top,long,府邸,st,巴士,CSP,define
From: https://www.cnblogs.com/403caorong/p/16717280.html

相关文章

  • 9.21-CSP-S模拟8
    T1JOI2022FinalT3「選挙で勝とう/Let'sWintheElection」赛时对着一个假贪心不知道为什么是错的。贪心就是枚举选几个协作州,然后贪心把小的都拿了,剩下的支持州......
  • CSP 2021
    普及分糖果(红)没有1A,身败名裂)点击查看代码#include<bits/stdc++.h>#definefffflush(stdout)#definethankputs("感恩......
  • CSP-S2022游记
    2022.9.18晚分数估出来了,63.5,比去年高(去年才三十几分啊/(ㄒoㄒ)/~),一部分原因是我的成长,还有一部分是因为确实比去年简单不少。单论分数我满意,一比较又觉得担心且不甘心。......
  • CSP-j/s 2022 第一轮(初赛)游记
    CSP-J/S2022第一轮游记HA(河南)省今年cspj报名人数较去年增长66%……挺离谱的eee由于没有疫情,初赛定在了线下举办,似乎今年pj要卡掉\(1e3\)个人左右CwC一些文中的名词......
  • CSP 2022 备战 高精度算法
    在考场上,有些题目,你用int只能拿30分开了longlong还是会爆这时候还得靠高精度算法来支持概念:将数字中的每一位存入数组中比如123,可以将它存入一个a[3]的数组中a[0]......
  • CSP-S模拟6 题解
    开个坑,今后我要写题解了!A.玩水挺有趣的一道题,我们首先从\(2\)条路径的情况考虑符合答案的路径一定满足这种格式:两条路径先重合,再分开,最后再重合观察一下,注意到第一......
  • CSP-S模拟6
    A.玩水一直以为这是\(dp\),但是只是一个性质/结论code#include<bits/stdc++.h>usingnamespacestd;typedeflonglongll;typedefunsignedlonglongull;i......
  • 归档 220920 | CSP-J 复习
    所以为什么要复习J组所以为什么我连J组都不会,哭唧唧A.加工零件一开始的想法是,如果点\(x\)离\(1\)的距离大于等于\(L\),且与\(L\)奇偶性相同,那么就可行。然......
  • CSP-S模拟7 序列问题 钱仓 自然数 环路
    T1:线性DP,求最长不下降子序列优化(cdp,树状数组)T2:断环为链,结论T3:序列上区间统计答案,线段树维护T4:咕了,矩阵乘法+分治优化,我就打个暴力T1:给你一个长度n的序列A(n<=5e5,ai<=......
  • CSP-S模拟7
    学校体检:内科:问,你是神经病吗;答,不是。下一个。外科:问,你做过手术吗;答,没有。下一个。基础检查:问,你身高体重是多少;答,……。下一个。此处应有乌鸦飞过*** A.序列问题我......