Codeforces #639 (div 1) 做题记录

随便写点题,按时间倒序随便刷刷

A.

如果有两个相等可以列等式(i+a_{i mod n}=j+a_{j mod n})

令(i=k_1n+p,j=k_2n+q),则有(k_1n+p+a_p=k_2n+q+a_q)

即存在(p,q),(p+a_p=q+a_q)在(mod n)意义下相等,这个直接判就行了

 1 #include<bits/stdc++.h>
 2 #define maxn 200005
 3 using namespace std;
 4 int T,n;
 5 int a[maxn];
 6 int main()
 7 {
 8     scanf("%d",&T);
 9     while(T--)
10     {
11         scanf("%d",&n);
12         for(int i=0;i<n;++i)scanf("%d",&a[i]);
13         for(int i=0;i<n;++i)a[i]=((a[i]+i)%n+n)%n;
14         sort(a,a+n);
15         bool fl=0;
16         for(int i=1;i<n;++i)if(a[i]==a[i-1])fl=1;
17         if(fl)puts("NO");
18         else puts("YES");
19     }
20 }
View Code

 B.

考虑同一行/同一列不能出现两个黑块中间有白块的情况:

如果有这样的情况,那么如果这两个黑块都是N磁铁可达的,那么在这行/列的其他位置必然有一个S磁铁,这样随便操作一下N磁铁就进白块了

所以每行/列最多一个连通块

如果是(0)个,那么需要单独考虑(因为每行每列都至少要有一个S,所以必须找出一个位置放S,而这样的位置必须是空行和空列的交点)

其他情况显然合法

最小个数就是每个连通块一个N磁铁

 1 #include<bits/stdc++.h>
 2 #define maxn 1005 
 3 using namespace std;
 4 int n,m;
 5 char a[maxn][maxn];
 6 bool vis[maxn][maxn];
 7 int id[maxn][maxn],cnt;
 8 void dfs(int x,int y)
 9 {
10     if(a[x][y]!='#')return;
11     if(vis[x][y])return;
12     vis[x][y]=1;
13     id[x][y]=cnt;
14     dfs(x+1,y);dfs(x-1,y);dfs(x,y+1);dfs(x,y-1);
15 }
16 int main()
17 {
18     scanf("%d%d",&n,&m);
19     for(int i=1;i<=n;++i)scanf("%s",a[i]+1); 
20     for(int i=1;i<=n;++i)
21         for(int j=1;j<=m;++j)if(a[i][j]=='#'&&(!vis[i][j]))
22         {
23             ++cnt;
24             dfs(i,j);
25         }
26     bool yes=1,y1=0,y2=0;
27     for(int i=1;i<=n;++i)
28     {
29         int lst=0;
30         for(int j=1;j<=m;++j)if(a[i][j]=='#')
31         {
32             if(!lst)lst=j;
33             else
34             {
35                 if(j==lst+1)lst=j;
36                 else yes=0;
37             }
38         }
39         if(!lst)y1=1;
40     }
41     for(int j=1;j<=m;++j)
42     {
43         int lst=0;
44         for(int i=1;i<=n;++i)if(id[i][j])
45         {
46             if(!lst)lst=i;
47             else
48             {
49                 if(i==lst+1)lst=i;
50                 else yes=0;
51             }
52         }
53         if(!lst)y2=1;
54     }
55     if(y1!=y2)yes=0;
56     if(!yes)puts("-1");
57     else printf("%d
",cnt);
58 }
View Code

 C.

先判有没有解

显然最松的约束是所有都是存在的情况,这个只要拓扑排序判环就行了

然后考虑找解

还是按照上面的图建图

因为每个变量的出现先后顺序是定的,所以如果某个变量(x_i)被定下来了,那么显然编号大于(i)的并且又和(i)存在大小关系的变量一定是存在

那么我们按编号从小往大考虑,如果一个变量没和之前的变量存在大小关系,那直接贪心的选成任意最优,否则是存在

这个存不存在大小关系就在图上dfs一下前驱后继标记一下就行了

 1 #include<bits/stdc++.h>
 2 #define maxn 200005
 3 using namespace std;
 4 int n,m;
 5 vector<int> g[maxn],g2[maxn];
 6 int d[maxn];
 7 char Ans[maxn];
 8 bool vis[maxn],vis2[maxn];
 9 void dfs(int u)
10 {
11     if(vis[u])return;
12     vis[u]=1;
13     for(int v:g[u])dfs(v);
14 }
15 void dfs2(int u)
16 {
17     if(vis2[u])return;
18     vis2[u]=1;
19     for(int v:g2[u])dfs2(v);
20 }
21 int main()
22 {
23     scanf("%d%d",&n,&m);
24     for(int i=1;i<=m;++i)
25     {
26         int u,v;
27         scanf("%d%d",&u,&v);
28         g[u].push_back(v);
29         g2[v].push_back(u);
30         d[v]++; 
31     }
32     queue<int> q;
33     for(int i=1;i<=n;++i)if(!d[i])q.push(i);
34     int has=0;
35     while(!q.empty())
36     {
37         int u=q.front();q.pop();
38         ++has;
39         for(int v:g[u])
40         {
41             --d[v];
42             if(!d[v])q.push(v);
43         }
44     }
45     if(has!=n)puts("-1");
46     else
47     {
48         int ans=0;
49         for(int i=1;i<=n;++i)
50         {
51             if(vis[i]||vis2[i])Ans[i]='E';
52             else Ans[i]='A',++ans;
53             dfs(i);
54             dfs2(i);
55         }
56         printf("%d
",ans);
57         printf("%s
",Ans+1);
58     }
59 }
View Code

 D.

一开始想到偏导上去了,但发现并不能处理(b_i leq a_i)的限制条件

考虑计算每次的增量: 在第(i)种从(b_i)到(b_{i+1})时,增量为(a_i-3b_i^2-3b_i-1)

有一个暴力的贪心做法是每次用堆维护最大的增量贪(k)次

但这个(k)很大

发现增量是单调递减的,我们二分最小增量(x),对每种再用一次二分求出(b_i)

这样剩下的零头不会超过(O(n)),按上面用堆贪一下就行了

 1 #include<bits/stdc++.h>
 2 #define maxn 100005
 3 #define ll long long 
 4 #define mp(a,b) make_pair(a,b)
 5 using namespace std;
 6 int n;
 7 ll k,a[maxn],b[maxn];
 8 ll calc(ll t)
 9 {
10     ll tot=0;
11     for(int i=1;i<=n;++i)
12     {
13         ll L=0,R=a[i],ans=0;
14         while(L<=R)
15         {
16             ll M=(L+R)/2;
17             if(a[i]-M*M*3-M*3-1>=t)ans=M,L=M+1;
18             else R=M-1;
19         }
20         b[i]=ans;
21         tot+=ans;
22     }
23     return tot;
24 }
25 int main()
26 {
27     scanf("%d%lld",&n,&k);
28     for(int i=1;i<=n;++i)scanf("%lld",&a[i]);
29     ll L=-(ll)4e18,R=(ll)2e9,ans=R;
30     while(L<=R)
31     {
32         ll M=(L+R)/2;
33         if(calc(M)<=k)ans=M,R=M-1;
34         else L=M+1;
35     }
36     calc(ans);
37     for(int i=1;i<=n;++i)k-=b[i];
38     priority_queue< pair<ll,int> > pq;
39     for(int i=1;i<=n;++i)if(b[i]<a[i])pq.push(mp(a[i]-b[i]*b[i]*3-b[i]*3-1,i));
40     for(int i=1;i<=k;++i)
41     {
42         int u=pq.top().second;pq.pop();
43         ++b[u];
44         if(b[u]<a[u])pq.push(mp(a[u]-b[u]*b[u]*3-b[u]*3-1,u));
45     }
46     for(int i=1;i<=n;++i)printf("%lld ",b[i]);
47 }
View Code
原文地址:https://www.cnblogs.com/uuzlove/p/12863639.html