CSP-S模拟41

CSP-S模拟41

A. 数轴取物(axis)

显然可以有一个 \(O(n^3)\) 的背包 dp,设 \(dp[i][j][k]\) 表示选区间 \([i,j]\),背包容量为 \(k\) 时可获得的最大价值。每次枚举固定左端点从小到大枚举右端点,发现 \(dp[i][j]\) 可以由 \(dp[i][j-1]\) 转移而来,那么直接背包做就完了。

然后你再设一个 \(f[i][j]\) 表示用前 \(i\) 个包走到位置 \(j\) 时可获得的最大价值。然后有一个 \(O(n^2 m)\) 的 dp 转移:枚举右端点,再枚举这个包所选物品区间左端点,直接可以转移。

然后 TLE 了。

然后你直接根据复杂度钦定固定右端点时指针从右往左动的最大次数,即可通过本题。

其实发现只有后 \(n\) 个包有用,前面的包可以直接跳过。那么 \(O(n^3)\) 即可通过。

Code:

    #include<bits/stdc++.h>
    #define int long long

    using namespace std;

    const int Size=(1<<20)+1;
    char buf[Size],*p1=buf,*p2=buf;
    char buffer[Size];
    int op1=-1;
    const int op2=Size-1;
    #define getchar()                                                              \
    (tt == ss && (tt=(ss=In)+fread(In, 1, 1 << 20, stdin), ss == tt)     \
        ? EOF                                                                 \
        : *ss++)
    char In[1<<20],*ss=In,*tt=In;
    inline int read()
    {
        int x=0,c=getchar(),f=0;
        for(;c>'9'||c<'0';f=c=='-',c=getchar());
        for(;c>='0'&&c<='9';c=getchar())
            x=(x<<1)+(x<<3)+(c^48);
        return f?-x:x;
    }
    inline void write(int x)
    {
        if(x<0) x=-x,putchar('-');
        if(x>9)  write(x/10);
        putchar(x%10+'0');
    }

    // #ifndef ONLINE_JUDGE
    // #define ONLINE_JUDGE
    // #endif

    int n,m;
    int a[205],b[205];
    int dp2[205][205][205];
    int dp[205][205];
    int r[205];
    int maxn[205];

    // #define max(x,y) ((x)>(y)?(x):y)

    inline int max(int x,int y) { return x>y?x:y; }

    signed main()
    {
        // axis
        // #ifndef ONLINE_JUDGE
        freopen("axis.in","r",stdin);
        freopen("axis.out","w",stdout);

        n=read();
        m=read();
        for(int i=1;i<=n;i++)
        {
            a[i]=read();
            b[i]=read();
        }
        for(int i=1;i<=n;i++)
        for(int j=i;j<=n;j++)
        for(int totval=0;totval<=200;totval++)
        {
            dp2[totval][j][i]=dp2[totval][j-1][i];
            if(totval>=a[j]) 
            dp2[totval][j][i]=max(dp2[totval][j][i],dp2[totval-a[j]][j-1][i]+b[j]);
        }
        // const int MAXN=min(200ll,max(10ll,(int)(3e8/(m*n))));
        // cout<<MAXN<<endl;
        for(int i=1;i<=m-n;i++) int x=read();
        m=min(n,m);
        for(int i=1;i<=m;i++)
        {
            int x=read();
            for(int j=1;j<=n;j++)
            for(int k=j+1;k>0;k--)
            dp[i][j]=max(dp[i][j],dp[i-1][k-1]+dp2[x][j][k]);

            // for(int j=1;j<=n;j++) 
            // maxn[j]=max(maxn[j-1],dp[i][j]),dp[i][j]=maxn[j];
        }
        int ans=0;R
        for(int i=1;i<=m;i++)
        for(int j=1;j<=n;j++)
        ans=max(ans,dp[i][j]);
        cout<<ans<<"\n";

        // #endif
        //mt19937_64 myrand(time(0));
        return 0;
    }Z

B. 排列变环(circle)

打表发现规律直接做。

Checker:

#include<bits/stdc++.h>
#define int long long

using namespace std;

const int Size=(1<<20)+1;
char buf[Size],*p1=buf,*p2=buf;
char buffer[Size];
int op1=-1;
const int op2=Size-1;
#define getchar()                                                              \
(tt == ss && (tt=(ss=In)+fread(In, 1, 1 << 20, stdin), ss == tt)     \
	? EOF                                                                 \
	: *ss++)
char In[1<<20],*ss=In,*tt=In;
inline int read()
{
	int x=0,c=getchar(),f=0;
	for(;c>'9'||c<'0';f=c=='-',c=getchar());
	for(;c>='0'&&c<='9';c=getchar())
		x=(x<<1)+(x<<3)+(c^48);
	return f?-x:x;
}
inline void write(int x)
{
	if(x<0) x=-x,putchar('-');
	if(x>9)  write(x/10);
	putchar(x%10+'0');
}

// #ifndef ONLINE_JUDGE
// #define ONLINE_JUDGE
// #endif

const int n=20;
int a[n+1];
int p[n+1],top;

int find(int *a)
{
    int cnt=0;
    for(int i=2;i<=n;i++)
    for(int j=1;j<i;j++)
    cnt+=(*(a+j))>(*(a+i));
    return cnt;
}

int do1()
{
    for(int i=top;i>1;i--)
    {
        int nw=p[i],pre=p[i-1];
        swap(a[nw],a[pre]);
    }
    // cout<<"Final for 1: ";
    // for(int i=1;i<=n;i++) cout<<a[i]<<" ";
    // cout<<"\n";
    int cnt=find(a);

    for(int i=2;i<=top;i++)
    {
        int nw=p[i],pre=p[i-1];
        swap(a[nw],a[pre]);
    }

    // cout<<"del for 1: ";
    // for(int i=1;i<=n;i++) cout<<a[i]<<" ";
    // cout<<"\n";
    return cnt;
}
int do2()
{
    for(int i=2;i<=top;i++)
    {
        int nw=p[i],pre=p[i-1];
        swap(a[nw],a[pre]);
    }
    // cout<<"Final for 2: ";
    // for(int i=1;i<=n;i++) cout<<a[i]<<" ";
    // cout<<"\n";
    int cnt=find(a);
    for(int i=top;i>1;i--)
    {
        int nw=p[i],pre=p[i-1];
        swap(a[nw],a[pre]);
    }

    // cout<<"del for 2: ";
    // for(int i=1;i<=n;i++) cout<<a[i]<<" ";
    // cout<<"\n";
    return cnt;
}

void dfs(int pos)
{
    if(pos>n)
    {
        if(top<2) return;
        // cout<<"\nChange position: ";
        // for(int i=1;i<=top;i++) cout<<p[i]<<" ";
        // cout<<"\n";
        int c1=do1();
        int c2=do2();
        // cout<<"cnt="<<c1<<"\n";
        if(c1!=(p[top]-p[1])*2-(top-1)) 
        { cout<<"Egg!\n";
            
        // cout<<"Change position: ";
        // for(int i=1;i<=top;i++) cout<<p[i]<<" ";
        // cout<<"\n";
        // cout<<"c1="<<c1<<" c2="<<c2<<"\n";
        exit(0);
        }
        // cout<<pos<<" "<<top<<" "<<c1<<" "<<c2<<"\n";
        // if(c1==c2) { cout<<"It is the same!"<<endl; return; }
        // else if(c1<c2) { cout<<"Plan 1 is the winner"<<endl; return; }
        // else { cout<<"Plan 1 is the winner"<<endl; return; }
        return;
    }
    dfs(pos+1);
    p[++top]=pos;
    dfs(pos+1);
    p[top]=0;
    top--;
}

signed main()
{
	// #ifndef ONLINE_JUDGE
	// freopen(".in","r",stdin);
	freopen("Checking.out","w",stdout);
	
    cout<<"Checking Perm "<<n<<":"<<endl;
    for(int i=1;i<=n;i++) a[i]=i;
    dfs(1);
    
    // #endif
	//mt19937_64 myrand(time(0));
	return 0;
}

Code:

#include<bits/stdc++.h>
#define int long long

using namespace std;

const int Size=(1<<20)+1;
char buf[Size],*p1=buf,*p2=buf;
char buffer[Size];
int op1=-1;
const int op2=Size-1;
#define getchar()                                                              \
(tt == ss && (tt=(ss=In)+fread(In, 1, 1 << 20, stdin), ss == tt)     \
	? EOF                                                                 \
	: *ss++)
char In[1<<20],*ss=In,*tt=In;
inline int read()
{
	int x=0,c=getchar(),f=0;
	for(;c>'9'||c<'0';f=c=='-',c=getchar());
	for(;c>='0'&&c<='9';c=getchar())
		x=(x<<1)+(x<<3)+(c^48);
	return f?-x:x;
}
inline void write(int x)
{
	if(x<0) x=-x,putchar('-');
	if(x>9)  write(x/10);
	putchar(x%10+'0');
}

// #ifndef ONLINE_JUDGE
// #define ONLINE_JUDGE
// #endif

int n,k;
int a[1<<20];
int ans=0x3f3f3f3f;
// priority_queue<int> p1,p2;
int b[1<<20];
int val[1<<20];
unordered_map<int,int> mp;

const int N=1e4+5;
struct Tree{
	int sum,cnt;
}t[N<<2];

#define lp (p<<1)
#define rp ((p<<1)|1)

const int MINN=0,MAXN=1e3+1;
void build(int l,int r,int p)
{
	t[p]={0,0};
	if(l==r) return;
	int mid=(l+r)>>1;
	build(l,mid,lp);
	build(mid+1,r,rp);
}

void pushup(int p)
{
	t[p].cnt=t[lp].cnt+t[rp].cnt;
	t[p].sum=t[lp].sum+t[rp].sum;
}

void add(int l,int r,int x,int p)
{
	if(l==r)
	{
		t[p].sum=val[x];
		t[p].cnt=1;
		return;
	}
	int mid=(l+r)>>1;
	if(x<=mid) add(l,mid,x,lp);
	else add(mid+1,r,x,rp);
	pushup(p);
}

int query(int l,int r,int sum,int p)
{
	if(l==r) return t[p].cnt&&((t[p].sum+sum)>=0);
	int mid=(l+r)>>1,ans=0;
	if(t[rp].sum+sum>=0)
	{
		sum+=t[rp].sum;
		ans+=t[rp].cnt;
		ans+=query(l,mid,sum,lp);
	}
	else ans+=query(mid+1,r,sum,rp);
	return ans;
}

signed main()
{
	// #ifndef ONLINE_JUDGE
	freopen("circle.in","r",stdin);
	freopen("circle.out","w",stdout);
	n=read();	
	k=read();
	for(int i=1;i<=n;i++) b[i]=a[i]=read();
	sort(b+1,b+1+n);
	b[0]=1e9+1;
	for(int i=1;i<=n;i++)
	{
		if(b[i]!=b[i-1]) mp[b[i]]=i;
		val[i]=b[i];
	}
	int sum=0;
	for(int i=1;i<=n;i++) 
	{
		sum+=a[i];
		int nw=a[i];
		a[i]=mp[nw];
		mp[nw]++;
	}
	// cout<<sum<<"\n";
	sum=0;
	// for(int i=1;i<=n;i++) cout<<a[i]<<" ";
	// cout<<"\n";
	// for(int i=1;i<=n;i++) sum+=val[i];
	// // cout<<sum<<"\n";
	// for(int i=1;i<=n;i++)
	// {
	// 	int sum=0;
	// 	for(int j=i;j<=n;j++)
	// 	{
	// 		sum+=val[a[j]];
	// 		if(sum>=k)
	// 		{
	// 			int len=j-i;
	// 			if(len==76)
	// 			{
	// 				cout<<i<<" "<<j<<"\n";
	// 			}
	// 		}
	// 	}
	// }
	/*
	
	6 86
	7 87
	472 552
	473 553
	81

	*/
	for(int i=1;i<=n;i++)
	{
		if(val[a[i]]>=k) ans=0;
		build(MINN,MAXN,1);
		int sum=val[a[i]];
		int cnt=1;
		for(int j=i+1;j<=n;j++)
		{
			int nw=sum+val[a[j]];
			// cout<<nw<<"\n";
			
			if(nw>=k)
			{
				int nwcnt=cnt+1+query(MINN,MAXN,nw-k,1);
				int nwans=(j-i)*2-nwcnt+1;
				ans=min(ans,nwans);
				// cout<<"\n["<<i<<","<<j<<"] sum="<<nw<<" query="<<query(MINN,MAXN,nw-k,1)<<" cnt="<<nwcnt<<" nwans="<<nwans<<"\n";
				// break;
			}

			if(val[a[j]]>=0)
			{
				sum+=val[a[j]];
				cnt++;
			}
			else add(MINN,MAXN,a[j],1);//,cout<<"val="<<val[a[j]]<<" p="<<a[j]<<"\n";
		}
		// cout<<"\n\n\n";
	}
	if(ans>=0x3f3f3f3f) ans=-1;
	cout<<ans<<"\n";
	
	// #endif
	//mt19937_64 myrand(time(0));
	return 0;
}

posted @ 2025-10-28 20:17  Wy_x  阅读(12)  评论(1)    收藏  举报