首页 > 其他分享 >正睿csp-s 7连测 day 7

正睿csp-s 7连测 day 7

时间:2024-10-27 10:08:59浏览次数:1  
标签:int mxn lst 连测 正睿 ans define csp first

总结

由于晚上六点尚处于机房的打摆时间,所以先颓了三十分钟。
\(5\) 分钟写完 t1,继续摆到七点。
t2 想了一会,一开始以为是先贪心 + dp,发现被样例卡了。然后再想了一个 dp + 贪心,过了大样例。好像过了?
t3 想了半小时,好像是线段树,但一时不知道维护什么。先写了一个 \(60\) 分暴力。
t4 看了一眼瞬间没有写的欲望。
结果:100+70+60+0
上了点分,开心。

解析

A. 庄园(manor)

难度:橙
从左到右枚举即可。


#include<bits/stdc++.h>
#define ll long long
#define mxn 5010
using namespace std;
ll n,q,l[mxn],r[mxn];
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    cin>>n;
    for(int i=1;i<=n;i++)cin>>l[i]>>r[i];
    cin>>q;
    for(int i=1;i<=q;i++){
        ll sx,sy,tx,ty,lst,ans=0;
        cin>>sx>>sy>>tx>>ty;
        if(sx>tx)swap(sx,tx),swap(sy,ty);
        lst=sy;
        for(int j=sx+1;j<=tx;j++){
            if(lst<l[j])ans+=l[j]-lst,lst=l[j];
            else if(lst>r[j])ans+=lst-r[j],lst=r[j];
            ans++;
        }
        ans+=abs(ty-lst);
        cout<<ans<<'\n';
    }
    return 0;
}

B. 背包(knapsack)

难度:绿
纯 \(dp\) 题。
在背包 \(dp\) 的同时维护价格大于 \(j\) 的珠宝的最大美丽度和即可。


#include<bits/stdc++.h>
#define mxn 10010
#define ll long long
#define pii pair<int,int>
#define mp make_pair
using namespace std;
ll n,m,k,ans,dp[mxn],sum[mxn];
pii a[mxn];
priority_queue<int> q;
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    cin>>n>>m>>k;
    for(int i=1;i<=n;i++){
        int v,w;cin>>v>>w;
        a[i]=mp(v,w);
    }
    sort(a+1,a+n+1);
    for(int i=n;i;i--){
        sum[i]=sum[i+1]+a[i].second;
        q.push(-a[i].second);
        if(q.size()>k)
            sum[i]+=q.top(),q.pop();
    }
    for(int i=1;i<=n;i++)
        for(int j=m;j>=a[i].first;j--){
            dp[j]=max(dp[j],dp[j-a[i].first]+a[i].second);
            ans=max(ans,dp[j]+sum[i+1]);
        }
    cout<<ans;
    return 0;
}

C. 填色(paint)

难度:蓝
假设 \(ans_i\) 为大小为 \(i\) 时的答案,\(cnt_i\) 为大小为 \(i\) 时的极大交替组数量。
则有:

\[ans_i=\sum\limits_{k\geq i}(k-i+1)*cnt_k=ans_{i+1}+\sum\limits_{k\geq i}cnt_k \]

考虑用线段树进行维护。


#include<bits/stdc++.h>
#define ll long long
#define mxn 200010
#define sll set<ll>::iterator
using namespace std;
set<ll> st;
ll n,q,col[mxn<<1],sum1[mxn<<2],sum2[mxn<<2];
namespace seg{
    void push_up(int rot){
        sum1[rot]=sum1[rot<<1]+sum1[rot<<1|1];
        sum2[rot]=sum2[rot<<1]+sum2[rot<<1|1];
    }
    void update(int rot,int l,int r,int pos,int val){
        if(l==r){
            sum1[rot]+=val,sum2[rot]+=val*pos;
            return;
        }
        int mid=(l+r)>>1;
        if(pos<=mid)update(rot<<1,l,mid,pos,val);
        else update(rot<<1|1,mid+1,r,pos,val);
        push_up(rot);
    }
    ll query(ll* tre,int rot,int l,int r,int x,int y){
        if(r<x||l>y)return 0;
        if(l>=x&&r<=y)return tre[rot];
        ll ret=0,mid=(l+r)>>1;
        if(mid>=l)ret+=query(tre,rot<<1,l,mid,x,y);
        if(mid<r)ret+=query(tre,rot<<1|1,mid+1,r,x,y);
        return ret;
    }   
}
namespace sol{
    ll lst,sze;
    void add(ll l,ll r){
        if(l>n)return;
        if(r<n)seg::update(1,1,n,r-l+1,1);
        else lst=l,sze=r-l+1;
    }
    void merge(ll x){
        sll it=st.find(x),it1,it2;
        it1=it2=it;
        it1--,it2++;
        if(x<=n)seg::update(1,1,n,x-*it1,-1);
        if(*it2<=n)seg::update(1,1,n,*it2-x,-1);
        st.erase(it);
        add(*it1,*it2-1);
    }
    void split(ll x){
        sll it1=st.lower_bound(x),it2=it1;
        it1--;
        if(*it2<=n)seg::update(1,1,n,*it2-*it1,-1);
        st.insert(x);
        add(*it1,x-1);
        add(x,*it2-1);
    }
}
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    cin>>n>>q;
    for(int i=1;i<=n;i++){
        cin>>col[i];
        col[i+n]=col[i];
    }
    st.insert(1);
    int lst=1;
    for(int i=1;i<=2*n;i++){
        if(i==2*n||col[i]==col[i+1]){
            sol::add(lst,i);
            st.insert(i+1);
            lst=i+1;
        }
    }
    while(q--){
        ll opt,x,y;cin>>opt;
        if(opt==1){
            cin>>x;
            ll ans=seg::query(sum2,1,1,n,x,n);
            ans-=(x-1)*seg::query(sum1,1,1,n,x,n);
            if(sol::sze>=x)
                ans+=min(n-sol::lst+1,sol::sze-x+1);
            cout<<ans<<'\n';
        }
        else{
            cin>>x>>y;
            x++;
            if(col[x]==y)continue;
            if(x>1){
                if(col[x]==col[x-1])sol::merge(x);
                else sol::split(x);
            }
            if(col[x]==col[x+1])sol::merge(x+1);
            else sol::split(x+1);            
            if(col[x+n]==col[x+n-1])sol::merge(x+n);
            else sol::split(x+n);
            if(x<n){
                if(col[x+n]==col[x+n+1])sol::merge(x+n+1);
                else sol::split(x+n+1);
            }
            col[x]=col[x+n]=y;
        }
    }
    return 0;
}

D. 小镇(town)

难度:紫

首先,我们先想一想要加几条特殊道路。

我们知道无向图中存在欧拉回路的条件是不存在度数为奇数的点。

而使一个连通图存在欧拉回路的方法为加入 度数为奇数的点数\(/2\) 条边。但这里还有很多可选道路,考虑如何处理。

记全体必经道路为 \(E_1\),可经道路为 \(E_2\)。记录每个结点在图 \(G_1=\langle V,E_1\rangle\) 中的度数,记作 \(deg_i\)。把点按照 \(deg_i\) 的奇偶性分成两类,奇为 \(A\) 点,偶为 \(B\) 点。

我们要用 \(E_2\) 中的边将 \(A\) 点两两相连。设图 \(G_2=\langle V,E_2\rangle\)。将 \(G_2\) 分成几个极大联通子图,设这些子图中有偶数个 \(A\) 点的称为 \(C\) 块,有奇数个的称为 \(D\) 块。

容易证明,\(C\) 块中的 \(A\) 点是可以通过 \(C\) 块中的路径两两相连的。\(D\) 块中的 \(A\) 点不能两两相连,因为到最后总会剩下一个 \(A\) 点。所以,特殊通道的数量为 \(D\) 块数量的一半。

然后想想至少走几条可选道路。

观察性质,我们发现 \(G_2\) 由一些基环树和树组成。

对于树,我们可以在上面加一个自环让其变成基环树。

现在我们考虑环上的每个点分出去的子树中最少需要走多少条可选道路。

若为 \(C\) 块,则树上只有一种情况,而环上则为两种,\(dfs\) 计算出即可。

若为 \(D\) 块,则可以 \(dp\) 出每个点连接特殊道路后最少走多少条。

懒得自己写了,就把官方solution放出来吧。


#include<bits/stdc++.h>
#define mxn 1000002
#define pb push_back
#define mp make_pair
#define pob pop_back
#define pii pair<int,int>
using namespace std;
vector<pii> e[mxn];
vector<int> vc,circle;
int c,type,n,m;
int deg[mxn],vis[mxn],sz[mxn];
int f[mxn],a[mxn],g[mxn];
int ans1,ans2;
void dfs1(int x,int& odd,int& nd,int& eg){//求出c块和d块数
	vis[x]=1;
	odd+=deg[x]&1;
	++nd;
	eg+=e[x].size();
	for(auto i:e[x])
		if(!vis[i.first])
			dfs1(i.first,odd,nd,eg);
}
bool dfs2(int x,int lst){//找环用
	vc.pb(x);
	vis[x]=2;
	for(auto i:e[x]){
		if(i.second!=lst){//不走父亲
			if(vis[i.first]==1){//尚未走过
				if(dfs2(i.first,i.second))
					return 1;
			} 
            else{//不走父亲但还是遇到了,说明是一个环
				while(vc.back()!=i.first){
					circle.pb(vc.back());
					vis[vc.back()]=3;//给环再打个标记
					vc.pob();
				}
				circle.pb(i.first);
				vis[i.first]=3;
				return 1;//有环,return 1
			}
        }
    }
	vc.pob();
	return 0;
}
int dfs3(int x,int lst){//C块上的dfs
	int ret=0;
	sz[x]=deg[x]&1;//看有多少A点
	for(auto i:e[x]){
		if(vis[i.first]!=3&&i.first!=lst){//若不是环上的点
			ret+=dfs3(i.first,x);
			sz[x]+=sz[i.first];
		}
    }
	return ret+(sz[x]&1);
}
int dfs4(int x,int lst){//D块上的dfs 相当于一个树形dp
	int ret=f[x];
	for(auto i:e[x]){
		if(vis[i.first]!=3&&i.first!=lst){
			f[i.first]=f[x]+(sz[i.first]&1?-1:1);
            //
			ret=min(ret,dfs4(i.first,x));
		}
    }
	return ret;
}
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    cin>>c>>type>>n>>m;
	for(int i=1;i<=m;++i){
		int u,v,w;
        cin>>u>>v>>w;
		if(w)++deg[u],++deg[v]; 
        else{
			e[u].pb(mp(v,i));
			e[v].pb(mp(u,i));
		}
	}
	for(int i=1;i<=n;++i){
		if(!vis[i]){//对于每一个连通分支
			int odd=0,nd=0,eg=0;
			dfs1(i,odd,nd,eg);
			if(odd&1)++ans1;//若为D块,ans1++
			if(eg==(nd-1)*2)//如果是一棵树
				e[i].pb(mp(i,m+1));//就建一个自环,当作环处理
			vc.clear();
			circle.clear();
			dfs2(i,0);
			int sum=0;
			for(int j:circle)//对于环上的每个点,算出其每个分支要多少
                sum+=dfs3(j,0);
			if(!(odd&1)){//为C块,自行处理
				int lst=0,s=0,cnt=0;
				for(int j:circle){
					++cnt;//cnt:环上有多少点
					if(sz[j]&1){//有多出来的
						--sum;//剩余的地方,dfs的时候实际上是多算了一次长度,要减掉
						if(lst)s+=cnt-lst,lst=0; 
                        else lst=cnt;
					}
				}
				ans2+=sum+min(s,cnt-s);//环上一共就两种情况,看一下哪个更小就行了
				continue;
			}
            else{//D块 总会有一个点连不上
                int cur=INT_MAX,op=-1,cnt=0,len=0;
                for(int j:circle){
                    ++len;
                    if(sz[j]&1)sum--,a[len]=op,op=-op; 
                    else a[len]=0; 
                    g[len]=g[len-1]+a[len]*len;
                }
                int lst=0;//枚举每一个A点需要与别的D块连
                for(int j:circle){
                    ++cnt;
                    int t1=dfs4(j,0),t2;
                    if(sz[j]&1){
                        t2=g[lst]-g[len]+g[cnt];
                        lst=cnt;
                    } 
                    else t2=g[lst]-a[lst]*cnt-g[len]+g[cnt];
                    cur=min(cur,t1+min(t2,len-t2));
                }
                ans2+=sum+cur;
            }
		}
    }
	ans1/=2;//每两个D块连一条边
    if(type==1)cout<<ans1;
    else cout<<ans2;
	return 0;
}

标签:int,mxn,lst,连测,正睿,ans,define,csp,first
From: https://www.cnblogs.com/nagato--yuki/p/18486448

相关文章

  • CSP-S2024 游寄
    上午放松了一下。中午吃完饭就来到了科技楼,我猛然想起自己忘了\(\text{tarjan}\)怎么打,于是赶紧问了智力。来到考场,发现周围还是有一群XXS,希望他们可以拉低一下1=线。考前安慰自己:没事没事,出事了也逝不了,只要不保单就行了。。。T1智障题。乱搞一下就过了。用时:3minT2......
  • CSP-S-2024 游记(寄)
    CSP-S-2024游记前言菜。Day-4补勰码题。补到了一半多。Day-3补勰码题。补到了二十多题。Day-2模拟赛,摆。0+0+0+0=0pts。复习了割点。打了两把区间加区间和线段树。情绪不太好。数据删除Day-1模拟赛,摆……不全是。10+20+20+0=50pts,甚至写了最低档暴力。垫底。不......
  • CSP-S2024 油鸡
    我往前飞飞过一片时间海我们也曾在爱情里受伤害我看着路梦的入口有点窄我遇见你是最美丽的意外总有一天我的谜底会揭开写得很水,应付yly,可能还要删除一些关键词。\(\textup{Day-114514}\)停课搞竞赛,但是国庆作业没写完被心旷神怡发现了,于是喜提停课半天体验......
  • CSP-S 2024 游记
    结婚!结婚!还是踏码的结婚!想到结婚后有杏菜在背后辅佐,补偿着生活的开销,心里就感到非常踏实。和杏菜结婚的话,女友,妻子,同学三个愿望一次满足,实在是人生的至福。啊,好想给杏菜戴上结婚戒指,一边听着杏菜说【这些钱我也要还吗?】,一边看着她把戒指当作一生宝物,一脸幸福的表情。Day-inf初......
  • CSP-J/S 2024 游记
    注:文章可能包含医疗建议。风起·忆往昔复白亘古事,诗人起歌喉。2023年的CSP,是我初登场的舞台。在舞台边的林荫下,不知是哪些同校的家长,三五成群地聚在一起,谈论着关于我的闲话。凉爽的秋风拂过树梢,仿若一位吟游诗人轻拨手中的木琴,令风声尽入我耳。“七年级的小L一点实力都......
  • [游记] [CSP-S 2024 复赛] 于是回家开始上物理课
    2024.10.26(Day1)记Day0上午打[cdqz大团队](?)的模板大赛,被薄纱。手速慢,还有几发没AC。下午写了个线段树2的板子,打算写CRT板子,发现不会exgcd求逆元,于是去重学exgcd,写了一点博客。晚上颓了一会儿,查了下C++的/和%,关于C++%到底是怎样的还是没搞清楚,决定先不管,......
  • 记一次CSP
    今年第一次参加CSP,当时还是很紧张的。早上是J组,很简单,但对我这个蒟蒻来说还是挺难的。T1很简单,开个二维数组把每张扑克牌映射到数组里最后看还剩多少个空着就行了T2但是看到题直接打了个搜索,结果看到题目已经给了总步数,又改了改,最后一个样例过不去了,打T3时才想起来可能爆栈了,改......
  • CSP-S 2024
    theendofmyOIday-7开始停课玩训练day-6~0打模拟赛,挂飞。day1上午打了打板子,rp++,14:10进考场,键盘打感还不错?就是enter为啥都恁奇怪。14:20试机,只打了快读,不知为何用不了-std=c++14?。14:30发pdf密码,复制密码错误,手打才对,神秘。14:35开T1,什么水题,10m......
  • CSP 2024 游记
    SH-S00652上海市大同中学(黄浦区南车站路353号)2号机房时行楼5楼504室座位号51考前考试前几天发现自己考场就在大同,这波是主场作战。但是大同只有Win7。考前一天在UOJ群里问Win7相比Win10有没有什么要注意的。有群友提醒,cmd中不能直接粘贴样例文本,要进......
  • csp-s 游记
    今天一天能把我累死!事情是这样的,由于没打板子,很慌!于是熬夜写板子写到了一点,然后睡了5h就去六中参加数学建模去了,然后中午12点到家,吃个饭就又得坐车去同一滨海去了,在车上浅浅睡了40min,然后发现到早了,在理塘和hwz等人聊天。随后进考场,难绷的是机房里的电脑全在播放宣传片()。......