Codeforces Round 36
Codeforces Round 36
蒟蒻的我并没有参加contest,比赛后打的,目前只写了4道题QWQ。
这这这真的就是一道水题
<题意概括>
给定n个水桶的数值,求在这n个水桶中能整除K的最大的数值。1<=n,k<=100.
直接枚举,因为只有一百,取最大的数。
Code
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<algorithm> #define maxn 120 #include<cmath> using namespace std; int read(){ int w=0;char c=getchar(); while(c<'0'||c>'9') c=getchar(); while(c>='0'&&c<='9') w=w*10+c-48,c=getchar(); return w; } int main(){ int n,length,i,b,ans=2147483647; n=read();length=read(); for(i=1;i<=n;i++){ b=read(); if(b==length){ printf("1");return 0; } if(length%b==0) ans=min(ans,length/b); } printf("%d",ans); }
<题意概括>
有一个1——n个窗口,有一个鼠标能在其中移动,每移动一个为一秒,在某个点时,
能关掉左边的窗口或右边的窗口(不包括它自己),时间均为一秒,求在这n个窗口中关掉除了[L,R[以外的窗口。
思路简单,but分的种类真的很恶心。一开始搞错了变量名WA了N次。。
分别对pos与l,r的关系进行分类。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<algorithm> #define maxn 120 #include<cmath> using namespace std; int read(){ int w=0;char c=getchar(); while(c<'0'||c>'9') c=getchar(); while(c>='0'&&c<='9') w=w*10+c-48,c=getchar(); return w; } int main(){ int t,n,pos,l,r; n=read();pos=read();l=read();r=read(); if(l==r) { t=abs(pos-l);if(l!=1) t++;if(r!=n) t++;} else if(l==1&&r==n) t=0; else if(pos==l){ if(l==1) t=r-l+1; else if(r==n) t=1; else t=2+r-l; } else if(pos==r){ if(l==1) t=1; else if(r==n) t=r-l+1; else t=2+r-l; } else if(pos<l){ if(r==n) t=1+l-pos; else t=2+r-pos; } else if(pos>r){ if(l==1) t=1+pos-r; else t=2+pos-l; } else { int mid=(l+r)/2; if(l==1){t=r-pos+1;} else if(r==n) t=pos-l+1; else if(pos<=mid){ t=pos-l+1+r-l+1; } else{ t=r-pos+1+r-l+1; // printf("mid:%d\n",mid); } } printf("%d",t); return 0; }
<题意概括>
在一个有向图中,存不存在一条边,使删除它之后图中不再存在环。存在则输出YES,否则输出NO。
刚开始思路是在图中找出任意一个环,然后枚举环上的每一条边,如果找到符合条件的边之后,直接输出。
若找不到,则说明不存在,输出NO。But后来发现自己在判断有没有环时出了错,应该用拓扑排序的。。
所以经过大佬的启发换了另外一种,(不要问我为什么不用拓扑排序找环),分别对每个点进行DFS,找出这个
有向图中有几个不独立的环(就是若这个环与另外一个环有公共边,则不算这个环),若找出符合以上条件的
环大于1个,则说明不可能存在符合题意的这样一条边了。
NOTICE:要对搜索过的边标记一种状态,对环中的边标记为另外一种状态,对既不在环中也不在被搜索过的队列中标为另外一种状态,第一二种状态不能标成同个。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<algorithm> #include<cstring> #define maxn 600 using namespace std; int vis[maxn],head[maxn],n,m,tot,cnt; struct Edge{ int to,next; }e[250000]; int read(){ int w=0;char c=getchar(); while(c<'0'||c>'9') c=getchar(); while(c>='0'&&c<='9') w=w*10+c-48,c=getchar(); return w; } void add(int x,int y){ e[++tot]=(Edge){y,head[x]}; head[x]=tot; } void dfs(int x){ vis[x]=2; for(int i=head[x];i;i=e[i].next){ if(vis[e[i].to]==2) cnt++; else if(!vis[e[i].to])dfs(e[i].to); } vis[x]=1; } int main(){ int x,y,i,j; n=read();m=read(); for(i=1;i<=m;i++){ x=read();y=read(); add(x,y); } for(i=1;i<=n;i++){ cnt=0; memset(vis,0,sizeof(vis)); dfs(i); for(j=1;j<=n&&cnt<=1;j++){ if(!vis[j]) dfs(j); } if(cnt<=1) {printf("YES");return 0;} } printf("NO"); return 0; }
<题意概括>
给定N个工作日,初始状态为工作日,操作1区间全部变为非工作日,操作2区间全部变为工作日,输出每一次修改后工作日的数量。
由于这道题的数据范围太大了啊,不能用普通线段树实现,所以需要用离散化思想。
叶子节点维护的不再只是一个点,而是一个区间,原理与普通线段树一样。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<set> #include<algorithm> #define maxn 1000050 using namespace std; int a[maxn],l[maxn],r[maxn],k[maxn]; struct tree{ int l,r,lazy,sum; }t[maxn*4]; int read(){ char c=getchar();int w=0; while(c<'0'||c>'9') c=getchar(); while(c>='0'&&c<='9'){ w=w*10+c-48;c=getchar(); } return w; } void pushdown(int rt){ if(~t[rt].lazy){ t[rt<<1].sum=(a[t[rt<<1].r]-a[t[rt<<1].l-1])*t[rt].lazy; t[rt<<1|1].sum=(a[t[rt<<1|1].r]-a[t[rt<<1|1].l-1])*t[rt].lazy; t[rt<<1].lazy=t[rt<<1|1].lazy=t[rt].lazy;t[rt].lazy=-1; } } void build(int rt,int l,int r){ t[rt].l=l;t[rt].r=r;t[rt].lazy=-1; if(l==r){t[rt].sum=a[l]-a[l-1];return;} int mid=(l+r)>>1; build(rt<<1,l,mid);build(rt<<1|1,mid+1,r); t[rt].sum=t[rt<<1].sum+t[rt<<1|1].sum; } void change(int rt,int l,int r,int x){ if(l<=t[rt].l&&t[rt].r<=r){ t[rt].lazy=x;t[rt].sum=(a[t[rt].r]-a[t[rt].l-1])*x;return; } pushdown(rt); int mid=(t[rt].l+t[rt].r)>>1; if(l<=mid) change(rt<<1,l,r,x); if(r>mid) change(rt<<1|1,l,r,x); t[rt].sum=t[rt<<1].sum+t[rt<<1|1].sum; } set<int> balance; int main(){ int n,q,i,tot=0; n=read();q=read(); for(i=1;i<=q;i++){ l[i]=read();r[i]=read();k[i]=read(); balance.insert(l[i]-1);balance.insert(r[i]); } if(*balance.begin()==0) balance.erase(balance.begin()); balance.insert(n); for(set<int>::iterator i=balance.begin();i!=balance.end();i++){ a[++tot]=*i; } for(i=1;i<=q;i++){ l[i]=lower_bound(a+1,a+tot+1,l[i])-a; r[i]=lower_bound(a+1,a+tot+1,r[i])-a; } build(1,1,tot); for(i=1;i<=q;i++){ change(1,l[i],r[i],k[i]-1); printf("%d\n",t[1].sum); } return 0; }