zoukankan      html  css  js  c++  java
  • 5月27日

    5月27日

    I'm always here if you need me.

    前传

    但是 There is no time you need me.

    三个人铃声响完挨着准备进信息教室,结果两个人进去之后,Mr俞把门关了,于是樊子奆就只能敲门了,关门3s后门开了,于是门上课时一直就没关。


    大扫除:

    卢宇宸准备去拿林烨手里的报纸:

    “不行!我还要看!”

    林烨可可爱爱,班长一脸无奈。

    季亦贝:同学们让一让,人家要擦空调了。

    林烨:对要擦扇贝。

    我觉得我可以进化成磕cp的人。


    “是1/2吧?你们不要不说话啊,我还以为我错了呢”

    “也不要当我是一点数学也不会啊”


    历史课下,眼保健操铃响了,殷准备去关铃。章云皓小朋友明目张胆skip out of the front door。

    “太过分了”前一秒

    “你们是不是要查操啊?那快去啊”后一秒


    和云再一次达成共识——单身快乐

    “还有没有什么要吐槽的?"

    "蔡蔡呢"

    “蔡蔡很好,蔡蔡没什么要吐槽的”

    “刘丽钧呢?”

    “小姑娘挺可爱的,就是做操不太认真,今天早上被杜林存骂了,骂的可狠了。

    CF1517E Group Photo

    2500开场,美好的一天。细节好烦啊,烦的我自闭了不过完完整整做了道题

    大概发现,一定是一段连着的,然后空一格的,最后一个(可以没有)和前面隔很远,于是就有了分类一下前后缀种类,就有了以下五种情况,这是暴力。

    		for (int i=n;i>=0 && pre[i]>suf[i+1];i--) ans++; 
    		for (int i=1;i<=n;i++)
    			for (int j=n;j>i;j--){
    				if ((j-i-1)&1) continue;
    				if (i>=2 && j<n) ans+=chk(i+1,j-1,suf[j]-2*a[n]-pre[i]+2*a[1]);//PCCC...PCPC...PPPC
    				if (i>=2) ans+=chk(i+1,j-1,suf[j]-pre[i]+2*a[1]);//PCCc...PPPP
    				if (j<n) ans+=chk(i+1,j-1,suf[j]-2*a[n]-pre[i]);//CCCC...PPPC
    				ans+=chk(i+1,j-1,suf[j]-pre[i]); //CCC...PPP
    			}
    

    然后发现因为随着j的后移,sumc会增大,所以i后移时,j一定是前移的,也就是有单调性。

    所以就可以分奇偶四种情况分别做一下就好了。

    #include <bits/stdc++.h>
    typedef long long ll;
    const int N=200005,mu=998244353;
    int T,n,a[N];
    ll s[N],ans,pre[N],suf[N];
    int chk(int l,int r,ll sum){
    	sum+=s[r]-s[l-1];
    	return sum>0;
    }
    void solve(int L,int R,int tg1,int tg2){
    	for (int i=L,j=R;i<=n;i+=2){
    		ll s1=pre[i];
    		if (tg1) s1-=2*a[1];
    		for (;;j--){
    			if (j<=i) return;
    			if ((j-1-i)&1) continue;
    			ll s2=suf[j];
    			if (tg2) s2-=2*a[n];
    			if (chk(i+1,j-1,s2-s1)) break;
    		} 
    		ans+=(j-i+1)/2;
    	}		
    }
    int main(){
    	scanf("%d",&T);
    	while (T--){
    		ans=0;
    		scanf("%d",&n);
    		for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    		for (int i=1;i<=n;i++){
    			if (i>2) s[i]=s[i-2]-a[i]+a[i-1]; 
    			pre[i]=pre[i-1]+a[i];
    		}
    		suf[n+1]=0;
    		for (int i=n;i>=1;i--) suf[i]=suf[i+1]+a[i];
    		//pppppcccc
    		for (int i=n;i>=0 && pre[i]>suf[i+1];i--) ans++; 
    		solve(2,n-1,1,1);
    		solve(3,n-1,1,1);
    		solve(2,n,1,0);
    		solve(3,n,1,0);
    		solve(1,n-1,0,1);
    		solve(2,n-1,0,1);
    		solve(1,n,0,0);
    		solve(2,n,0,0);
    		printf("%lld
    ",ans%mu);
    	}
    } 
    

    决策单调性,思维,细节

    CF1510B Button Lock

    d很小,可以暴力建一张图,每个点向它的子集连边。

    像最小链覆盖一样,但是这里我们不止要考虑链的条数,还要考虑最多串中1的个数。

    大概就是先假装所有链顶无父亲,假装源点是父亲,要暴力构造清零 ((S,x',|s_x+1|)) ,然后左边一列出点,右边一列入点,((x,y',0)) 表示把 (y) 继承于 (x) 后可以省下的,((S,x,1,0)),((x',T,1,0)) 保证每个点都考虑到,最小费用最大流即可

    好像就做完了,输出方案再做一做就好了。

    #include <bits/stdc++.h>
    const int M=70005,N=2205,INF=1e9;
    char s[N][10];
    int n,m,edge,last[N],Next[M<<1],w[M<<1],to[M<<1],d[N],cnt,match[N];
    int dis[N],vis[N],v[M<<1],flow[N],S,T,a[N],f[N],id[N][N];
    std::queue<int> q;
    void add(int x,int y,int ww,int zz){
    	//printf("%d %d %d %d
    ",x,y,ww,zz);
    	to[++edge]=y;
    	Next[edge]=last[x];
    	last[x]=edge;
    	w[edge]=ww;
    	v[edge]=zz;
    }
    int c(int x){
    	return (x&1)?x+1:x-1;
    }
    void Add(int x,int y,int ww,int zz){
    	add(x,y,ww,zz);
    	add(y,x,0,-zz);
    }
    bool chk(int x,int y){
    	for (int i=0;i<m;i++)
    		if (s[y][i]=='1' && s[x][i]=='0') return 0;
    	return 1;
    }
    bool SPFA(){
    	memset(dis,0x3f,sizeof(dis));
    	memset(flow,0x3f,sizeof(flow));
    	dis[S]=0;
    	q.push(S);
    	vis[S]=1;
    	while (q.size()){
    		int x=q.front();
    		q.pop();
    		vis[x]=0;
    		for (int i=last[x];i;i=Next[i]){
    			int u=to[i];
    			if ((!w[i]) || dis[x]+v[i]>=dis[u]) continue;
    			dis[u]=dis[x]+v[i];
    			f[u]=i;
    			flow[u]=std::min(flow[x],w[i]);
    			if (!vis[u]) q.push(u),vis[u]=1;
    		}
    	}
    	return dis[T]<INF;
    }
    struct Edge{
    	int x,y,id;
    }e[M];
    int main(){
    	scanf("%d%d",&m,&n);
    	for (int i=1;i<=n;i++){
    		scanf("%s",s[i]);
    		int cnt=0;
    		for (int j=0;j<m;j++)
    			if (s[i][j]=='1') cnt++;
    		a[i]=cnt;
    	}
    	S=2*n+1,T=S+1;
    	for (int i=1;i<=n;i++) Add(S,i,1,0),Add(S,i+n,1,a[i]+1),Add(i+n,T,1,0);
    	for (int i=1;i<=n;i++)
    		for (int j=1;j<=n;j++){
    			if (i==j) continue;
    			if (chk(i,j)) Add(i,j+n,1,0),e[++cnt]={i,j,edge}; 
    		}
    	int cost=-1;
    	while (SPFA()){
    		cost+=dis[T]*flow[T];
    		int u=T;
    		while (u!=S){
    			w[f[u]]-=flow[T];
    			w[c(f[u])]+=flow[T];
    			u=to[c(f[u])];
    		}
    	}
    	printf("%d
    ",cost);
    	for (int i=1;i<=cnt;i++)
    		if (w[e[i].id]){
    			match[e[i].y]=e[i].x;
    			d[e[i].x]++;
    		}
    	int tg=0;
    	for (int i=1;i<=n;i++){
    		if (d[i]) continue;
    		if (tg) printf("%c ",'R');
    		tg=1;
    		int u=i;
    		for (int j=0;j<m;j++) if (s[u][j]=='1') printf("%d ",j);
    		while (match[u]){
    			int v=match[u];
    			for (int j=0;j<m;j++)
    				if (s[v][j]=='1' && s[u][j]=='0') printf("%d ",j);
    			u=v;
    		}
    	}
    }
    

    网络流

    逐渐因懒于看题解而学会自己做题

    CF1521E Nastia and a Beautiful Matrix

    想了一下。

    下界,肯定就是四个都填三个,角的地方顶上。

    上界,直接一行空一行,答案一定是 (sqrt n) 级别的。

    有一种感觉,是先隔行填了,然后,选不相同的填上去,只要不冲突即可达到下界。那么一定是先众数全填,别的数填完,然后去补众数下面的,也就是如果众数 (x le 2(n-x)) 那么就做完了。

    有点问题,其他数填到最后会崩。那就不要隔行,先四个格子填一个,填满一遍在每个格子填第二个,就行了,这样就不会崩了。

    如果 大于 的话。那也做完了?每四个格子最多两个众数,众数填完别的随便填就好了。

    想不清楚 我们来找一个短一点的 题解 瞧一瞧

    查了半天错回去发现掉落re...原来数组开小了

    #include <bits/stdc++.h>
    int T,n,m,a[100005];
    int c[600][600],ans;
    void solve(int t1,int t2,int x,int &mx){//填众数,尽量使接下来的数不会冲突,也就是剩下非对角线
    	if (!mx) return;
    	for (int i=t1;i<=ans;i+=2)
    		for (int j=t2;j<=ans;j+=2){
    			c[i][j]=x,mx--;	
    			if (!mx) return;
    		}
    }
    void solve2(int t1,int t2,int &p){//按不同格依次填,保证不会冲突
    	for (int i=t1;i<=ans;i+=2)
    		for (int j=t2;j<=ans;j+=2){
    			if (c[i][j]) continue;
    			while (p<=m && (!a[p])) p++;
    			if (p>m) return;
    			c[i][j]=p;
    			a[p]--;
    		}
    }
    int main(){
    	scanf("%d",&T);
    	while (T--){
    		scanf("%d%d",&n,&m);
    		int mx=0,x=0;
    		for (int i=1;i<=m;i++){
    			scanf("%d",&a[i]);
    			if (a[i]>mx) mx=a[i],x=i; 
    		}
    		int L=(int)sqrt(n),R=(int)sqrt(n*2)+1;
    		while (L<=R){
    			int mid=(L+R)>>1,s,s2;
    			if (mid&1) s=(mid-1)*(mid-1)/4*3+mid+mid-1;
    			else s=mid*mid/4*3;
    			s2=((mid+1)/2)*mid;
    			if (s>=n && s2>=mx) ans=mid,R=mid-1;
    			else L=mid+1; 
    		}
    		printf("%d
    ",ans);
    		for (int i=1;i<=ans;i++)
    			for (int j=1;j<=ans;j++) c[i][j]=0;
    		solve(1,2,x,mx);
    		solve(1,1,x,mx);
    		a[x]=0;
    		int p=1;
    		solve2(1,2,p);
    		solve2(1,1,p);
    		solve2(2,1,p);
    		for (int i=1;i<=ans;i++,puts(""))
    			for (int j=1;j<=ans;j++) printf("%d ",c[i][j]);
    	}
    }
    

    CF1442D Sum

    2800冲冲冲!

    PA: 2800以上的就不要去做了。于是每日计划2500+2600+2700+2800 的快乐生活开始了。

    堆?凸包?背包?...题解!

    我们来思考一个问题,如果你当前选了一个你不想选的,那一定是因为后面有一个值得选的,那如果后面值得选了,那因为不降,后面那一连串都值得,感性理解,一个数组会被全选完。最多会有一个因 (k) 的限制而无法选到。还是题解比较理性一点。

    问题转化,对于全选的数组,一定按总和与个数的比择优选择。

    所以枚举最后那个数组,把别的排个序,扫一遍取前多少个?

    发现他wa了,感觉这个思路不太行,需要用到背包,又是一个缺一背包,可以用分治来做。

    但是开始想一个问题,如果这个东西没有选完,那排序后比他小的还会被完全选吗?当然会,所以乖乖地明天早上来写分治吧!冲题量失败。

    #include <bits/stdc++.h>
    typedef long long ll;
    using namespace std;
    const int N=3005;
    int n,k,siz[N],cnt;
    ll dp[N],ans,tmp[20][N];
    vector<int> a[N]; 
    struct point{
    	ll x;
    	int v;
    }b[N];
    void upd(int x,ll y){
    	for (int i=k;i>=x;i--)
    		dp[i]=std::max(dp[i-x]+y,dp[i]);
    }
    void solve(int L,int R){
    	if (L==R){
    		ll sum=0;
    		for (int i=1;i<=siz[L] && i<=k;i++){
    			sum=sum+a[L][i-1];
    			ans=std::max(ans,sum+dp[k-i]);
            }
    		return;
    	}
    	int now=++cnt;
    	memcpy(tmp[now],dp,sizeof(dp));
    	int mid=(L+R)>>1; 
    	for (int i=mid+1;i<=R;i++)
    		upd(b[i].v,b[i].x);
    	solve(L,mid);
    	memcpy(dp,tmp[now],sizeof(dp));
    	for (int i=L;i<=mid;i++)
    		upd(b[i].v,b[i].x);
    	solve(mid+1,R);
    	memcpy(dp,tmp[now],sizeof(dp));
    	cnt--; 
    }
    int main(){
    	scanf("%d%d",&n,&k);
    	for (int i=1;i<=n;i++){
    		ll sum=0;
    		scanf("%d",&siz[i]);
    		a[i].resize(siz[i]);
    		for (int j=0;j<siz[i];j++)
    			scanf("%d",&a[i][j]),sum+=a[i][j];
    		b[i]={sum,siz[i]};
    	}
    	solve(1,n);
    	printf("%lld
    ",ans);
    }
    

    分治,dp,结论

    1-mid的悲剧....

    * 生而自由 爱而无畏 *
  • 相关阅读:
    记一次把聊天表情包转成文件再还原的故事
    apue第九章之孤儿进程组
    Anatomy of a Database System学习笔记
    Anatomy of a Database System学习笔记
    Anatomy of a Database System学习笔记
    Anatomy of a Database System学习笔记
    Caffe学习中的一些错误记录
    接口自动化测试
    接口测试
    HTTP 协议相关
  • 原文地址:https://www.cnblogs.com/flyfeather6/p/14821098.html
Copyright © 2011-2022 走看看