首页 > 其他分享 >CSP2024 前集训:csp-s模拟9

CSP2024 前集训:csp-s模拟9

时间:2024-10-07 20:22:44浏览次数:6  
标签:unlocked int void CSP2024 Tp csp read inline 集训

前言

image

T1 状压挂了 \(10pts\),貌似做法是假的,但是一下午也没调出来哪儿假了,但是错误率很低,几百组能有一组错的。

T2 赛时数据锅了赛后重测了,赛时想到线段树但是没能具体实现,最后无奈写暴力。

T3、T4 没看。

T1 邻面合并

\(m\le 8\) 所以考虑状压表示每一行哪些地方被覆盖,对与相邻两行的状态进行合并转移即可。

点击查看代码(90pts)
#include<bits/stdc++.h>
#define ll long long 
#define endl '\n'
#define sort stable_sort
using namespace std;
const int N=110,M=310;
template<typename Tp> inline void read(Tp&x)
{
	x=0;register bool z=true;
	register char c=getchar_unlocked();
	for(;!isdigit(c);c=getchar_unlocked()) if(c=='-') z=0;
	for(;isdigit(c);c=getchar_unlocked()) x=(x<<1)+(x<<3)+(c^48);
	x=(z?x:~x+1);
}
template<typename T,typename ...Tp> inline void read(T &x,Tp &...y){read(x);read(y...);}
template<typename Tp> inline void wt(Tp x){if(x>9)wt(x/10);putchar_unlocked((x%10)+'0');}
template<typename Tp> inline void write(Tp x){if(x<0)putchar_unlocked('-'),x=~x+1;wt(x);}
template<typename T,typename ...Tp> inline void write(T x,Tp ...y){write(x);putchar_unlocked(' ');write(y...);}
int n,m,mx,ans=0x3f3f3f3f,f[N][M],g[M][M]; vector<int>e[N];
int calc(int s,int t)
{
	if(g[s][t]!=-1) return g[s][t]; int res=0;
	for(int i=0,now=0;i<=m;i++) if(!((t>>i)&1))
	{
		if(now>=i) {now=i+1; continue;}
		if((s>>i)&1) res++;
		else if(now&&((s>>(now-1))&1)) res++;
		else for(int j=now;j<=i-1;j++) if(!((s>>j)&1)) {res++; break;}
		now=i+1;
	}
	return g[s][t]=res;
}
signed main()
{
	freopen("merging.in","r",stdin),freopen("merging.out","w",stdout);
	read(n,m),mx=(1<<m)-1;
	for(int i=1,sta;i<=n;i++)
	{
		sta=0; for(int j=1,x;j<=m;j++) read(x),sta|=x<<(j-1);
		for(int j=0;j<=mx;j++) if((j|sta)==sta) e[i].push_back(j);
	}
	memset(f,0x3f,sizeof(f)),memset(g,-1,sizeof(g));
	for(int s:e[1]) f[1][s]=calc(0,s)+calc(0,e[1].back()^s);
	for(int i=2;i<=n;i++) for(int s:e[i]) for(int t:e[i-1]) 
		f[i][s]=min(f[i][s],f[i-1][t]+calc(t,s)+calc(e[i-1].back()^t,e[i].back()^s));
	for(int s:e[n]) ans=min(ans,f[n][s]);
	write(ans);
}

T2 光线追踪

  • 部分分 \(30pts\):直接暴力。

  • 正解:

    以角度为下标开线段树,对于每个矩形对应一段连续的角度区间,所以是区间修改最小值;每次查询对应一个角度,单点查询最小值。

    由于最小值不好处理不放开两棵线段树,一个存横坐标一个存纵坐标,最后根据斜率比较这两个哪一个先碰到即可。

    对于实现的细节,可以使用离散化处理,由于是单点查区间修,所以不用 pushup 但是需要 pushdown。

    点击查看代码
    #include<bits/stdc++.h>
    #define ll long long 
    #define endl '\n'
    #define sort stable_sort
    using namespace std;
    const int N=1e5+10; const double eps=1e-8;
    template<typename Tp> inline void read(Tp&x)
    {
        x=0;register bool z=true;
        register char c=getchar_unlocked();
        for(;!isdigit(c);c=getchar_unlocked()) if(c=='-') z=0;
        for(;isdigit(c);c=getchar_unlocked()) x=(x<<1)+(x<<3)+(c^48);
        x=(z?x:~x+1);
    }
    template<typename T,typename ...Tp> inline void read(T &x,Tp &...y){read(x);read(y...);}
    template<typename Tp> inline void wt(Tp x){if(x>9)wt(x/10);putchar_unlocked((x%10)+'0');}
    template<typename Tp> inline void write(Tp x){if(x<0)putchar_unlocked('-'),x=~x+1;wt(x);}
    template<typename T,typename ...Tp> inline void write(T x,Tp ...y){write(x);putchar_unlocked(' ');write(y...);}
    int n,m;
    struct aa {int op,x1,y1,x2,y2;}e[N];
    struct bb 
    {
        int x,y;
        bool operator < (const bb &a) const {return 1ll*y*a.x<1ll*a.y*x;}
        bool operator == (const bb &a) const {return 1ll*y*a.x==1ll*a.y*x;}
    }b[N<<2];
    struct cc
    {
        int val=1e9,id=0;
        bool operator < (const cc &a) const {return val==a.val?id>a.id:val<a.val;}
    };
    struct tree
    {
        #define ls (p<<1)
        #define rs (p<<1|1)
        #define mid (l+r>>1)
        cc val[N<<4],add[N<<4];
        void spread(int p)
        {
            if(add[p]<val[ls]) val[ls]=add[ls]=add[p];
            if(add[p]<val[rs]) val[rs]=add[rs]=add[p];
            add[p]=(cc){(int)1e9,0};
        }
        void change(int p,int l,int r,int vl,int vr,cc d)
        {
            if(vl<=l&&vr>=r) 
            {
                if(d<val[p]) val[p]=add[p]=d;
                return ;
            }
            if(add[p].id) spread(p);
            if(vl<=mid) change(ls,l,mid,vl,vr,d);
            if(vr>mid) change(rs,mid+1,r,vl,vr,d);
        }
        cc ask(int p,int l,int r,int x)
        {
            if(l==r) return val[p];
            if(add[p].id) spread(p);
            return x<=mid?ask(ls,l,mid,x):ask(rs,mid+1,r,x);
        }
    }t1,t2;
    signed main()
    {
        freopen("raytracing.in","r",stdin);
        freopen("raytracing.out","w",stdout);
        read(n);
        for(int i=1,op,x1,y1,x2,y2;i<=n;i++)
        {
            read(op,x1,y1); 
            if(op&1) read(x2,y2),b[++m]=(bb){x1,y2},b[++m]={x2,y1};
            e[i]=(aa){op,x1,y1,x2,y2},b[++m]=(bb){x1,y1};
        }
        sort(b+1,b+1+m),m=unique(b+1,b+1+m)-(b+1);
        for(int i=1,op,x1,y1,x2,y2;i<=n;i++)
        {
            op=e[i].op,x1=e[i].x1,y1=e[i].y1,x2=e[i].x2,y2=e[i].y2;
            if(op&1)
            {
                int s1=lower_bound(b+1,b+1+m,(bb){x2,y1})-b,
                    s2=lower_bound(b+1,b+1+m,(bb){x1,y1})-b,
                    s3=lower_bound(b+1,b+1+m,(bb){x1,y2})-b;
                if(y1) t1.change(1,1,m,s1,s2,(cc){y1,i});
                if(x1) t2.change(1,1,m,s2,s3,(cc){x1,i});
            }
            else
            {
                int s=lower_bound(b+1,b+1+m,(bb){x1,y1})-b;
                cc ans1=t1.ask(1,1,m,s),ans2=t2.ask(1,1,m,s);
                if(!ans1.id) write(ans2.id);
                else if(!ans2.id) write(ans1.id);
                else
                {
                    double k=1.0*y1/x1;
                    write((1.0*ans1.val-1.0*ans2.val*k<-eps||(abs(1.0*ans1.val-1.0*ans2.val*k)<=eps&&ans1.id>ans2.id))?ans1.id:ans2.id);
                }
                puts("");
            }
        }
    }
    

T3 百鸽笼

还没打。

T4 滑稽树下你和我

还没打。

标签:unlocked,int,void,CSP2024,Tp,csp,read,inline,集训
From: https://www.cnblogs.com/Charlieljk/p/18449740

相关文章

  • 2024初秋集训——提高组 #32
    B.序列删除题目描述有一个长度为\(2N\)的序列\(A\),其中\(1\)到\(N\)恰好出现两次。你每次可以选择两个相同的数\(A_l,A_r(l<r)\)并花费\(r-l\)的代价将其删除。求将整个序列删空的最小代价。思路有一个很显然的贪心就是:每次取代价最小的两个数删除。所以我们按照......
  • CSP 联训 3
    好吧,又倒数了,就签了个T2,100pts。T1我把相同颜色的存起来,每种颜色找出枚举选哪两个座位不合法的矩阵的左上和右下,如果找到的矩阵左下和右上也相同,则这个矩阵确实不合法,减去,但判断左下和右上的时候写的太急(最后十五分钟才开始打这个暴力)少判了和当前颜色是否相同,挂了80pts,!总......
  • CSP2024 前集训:多校A层冲刺NOIP2024模拟赛03
    前言T1没想到正难则反,脑瘫了没敢用bitset(复杂度擦边但卡常能过),T2空间开大了挂了\(100pts\),\(T3\)是原。T1五彩斑斓部分分\(20pts\):\(O(n^4)\)暴力。部分分\(20+?pts\):进行一些优化,极限数据下仍是\(O(n^4)\)。部分分\(60\sim100pts\):bitset优化一下,\(O(\f......
  • 雅礼国庆集训 day1 T2 折射
    题面题面下载算法转化题意说白了就是给了你一堆点,让你数这种折线有多少个(严格向下走,并且横坐标之间的差越来越小)看着像一种在y轴方向排序的dp但是由于是折线,所以需要加一维来判断转向dp设计状态设计\(dp_{i,0/1}\)表示第i个点,是向左下还是右上状态转移......
  • 雅礼国庆集训 day1 T1 养花
    题面题目下载算法考虑当\(k\)确定的时候如何求答案,显然对于所有形如\([ak,(a+1)k)\)的值域区间,最大值一定是最优的似乎怎么都是\(O(n^2)\)的算法观察到\(a_i\)的值域比较小,所以考虑桶显然对于一段区间\([L,R]\)我们可以推出其\(modk\)的最大值方法......
  • 2024.7.26 集训笔记
    单调栈给定一个长度为\(n\)的数列\(a\),对每个数字求出其右/左边第一个值大于等于它的数字的位置。考虑从左到右扫整个序列,维护一个栈,里面存放可能成为答案的数字,当遍历到一个新的数\(a_i\)的时候,可以发现栈中\(\leqa_i\)的数就再也不可能成为答案了,那就把它们弹掉,此时......
  • [CSP-S 2021] 回文
    算法暴力容易发现双指针可以找到每一个区间\([L,R]\),使得这个区间覆盖\(1\)~\(n\)的每一个数,也即区间外覆盖\(1\)~\(n\)的每一个数,这是\(O(n)\)的考虑判断对于两个数列\(A\),\(B\)显然,在\(A\)中先取出的要在\(B\)中最后取出,所以把\(A\)压入栈......
  • 信息学奥赛复赛复习14-CSP-J2021-03网络连接-字符串处理、数据类型溢出、数据结构Map
    PDF文档公众号回复关键字:202410071P7911[CSP-J2021]网络连接[题目描述]TCP/IP协议是网络通信领域的一项重要协议。今天你的任务,就是尝试利用这个协议,还原一个简化后的网络连接场景。在本问题中,计算机分为两大类:服务机(Server)和客户机(Client)。服务机负责建立连接,客户机......
  • CSP-S 模拟赛 35
    CSP-S模拟赛35rnk14,\(45+45+15+18=123\)。T1送花愚蠢题。看到区间想到线段树,预处理出每个位置的颜色上一次出现的位置,记为\(\mathit{las}_i\)。从左到右扫右端点,给\([\max(1,\mathit{las}_{\mathit{las}_i}),\mathit{las}_i]\)减去\(d(c_i)\),给\((\mathit{las}_i,i]\)......
  • CSP-S 模拟赛 34
    CSP-S模拟赛34rnk12,\(24+50+20+0=94\)。T1玩游戏有一个痿正解:从\(k\)到\(1\)扫左端点,对于每个左端点扫它最远能到达的右端点。如果在任何一时刻它的右端点位置\(<k\),则断定输出No。否则检查当左端点到\(1\)时右端点能否到\(n\)。注意这里扫右端点的方式,不要每次都......