codeforces #601 (div 1) 做题记录

A.

显然构造一个蛇形就行了

复杂度(O(r*c))

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 #define ull unsigned long long
 4 #define pii pair<int,int>
 5 #define pll pair<long long,long long>
 6 #define mpr(a,b) make_pair(a,b) 
 7 #define maxn 105
 8 using namespace std;
 9 ll gcd(ll a,ll b){if(!b)return a;return gcd(b,a%b);}
10 ll fastpow(ll a,ll p,ll mod)
11 {
12     ll ans=1;
13     while(p)
14     {
15         if(p&1)ans=ans*a%mod;
16         a=a*a%mod;p>>=1;
17     }
18     return ans;
19 }
20 ll inv(ll x,ll mod){return fastpow(x,mod-2,mod);} 
21 int T,n,m,k;
22 char a[maxn][maxn];
23 int Ans[maxn][maxn];
24 int nx[maxn][maxn],ny[maxn][maxn];
25 char ID(int x)
26 {
27     if(1<=x&&x<=26)return x-1+'a';
28     if(27<=x&&x<=52)return x-27+'A';
29     if(53<=x&&x<=62)return x-53+'0';
30 }
31 int main()
32 {
33     scanf("%d",&T);
34     while(T--)
35     {
36         scanf("%d%d%d",&n,&m,&k);
37         for(int i=0;i<=n+1;++i)
38             for(int j=0;j<=m+1;++j)nx[i][j]=ny[i][j]=Ans[i][j]=0;
39         for(int i=1;i<=n;++i)
40         {
41             for(int j=1;j<=m;++j)nx[i][j]=i,ny[i][j]=(i&1)?j+1:j-1;
42             if(i&1)nx[i][m]=i+1,ny[i][m]=m;
43             else nx[i][1]=i+1,ny[i][1]=1;
44         }
45         for(int i=1;i<=n;++i)scanf("%s",a[i]+1);
46         int num=0;
47         for(int i=1;i<=n;++i)
48             for(int j=1;j<=m;++j)if(a[i][j]=='R')num++;
49         int t=num/k;
50         int k1=num-t*k;
51         int k2=k-k1;
52         int nowx=1,nowy=1;
53         for(int p=1;p<=k1;++p)
54         {
55             int cnt=0;
56             while(cnt<t+1)
57             {
58                 Ans[nowx][nowy]=p;
59                 if(a[nowx][nowy]=='R')cnt++;
60                 int xx=nx[nowx][nowy],yy=ny[nowx][nowy];
61                 nowx=xx,nowy=yy;
62             }
63         }
64         for(int p=k1+1;p<=k1+k2;++p)
65         {
66             int cnt=0;
67             while(cnt<t)
68             {
69                 Ans[nowx][nowy]=p;
70                 if(a[nowx][nowy]=='R')cnt++;
71                 int xx=nx[nowx][nowy],yy=ny[nowx][nowy];
72                 nowx=xx,nowy=yy;
73             } 
74         }
75         while(nowx&&nowy)
76         {
77             Ans[nowx][nowy]=k1+k2;
78             int xx=nx[nowx][nowy],yy=ny[nowx][nowy];
79             nowx=xx,nowy=yy;
80         }
81         for(int i=1;i<=n;++i)
82         { 
83             for(int j=1;j<=m;++j)printf("%c",ID(Ans[i][j]));
84             puts("");
85         } 
86     }
87 }
View Code

B.

设总和为(tot),则我们考虑枚举(tot)的约数,然后check

假设这个约数是(k)

check做法:先把每个数 ( mod k),然后把一段一段和为(k)的段抠出来

然后枚举移动到的位置,取最优

这样B1就做完了,复杂度(O(n*d(w)))

然后发现B2的(tot)太大,约数太多,因此我们只需要考虑枚举其质因子即可

复杂度(O(n log w))

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 #define ull unsigned long long
 4 #define pii pair<int,int>
 5 #define pll pair<long long,long long>
 6 #define mpr(a,b) make_pair(a,b)
 7 using namespace std;
 8 ll gcd(ll a,ll b){if(!b)return a;return gcd(b,a%b);}
 9 ll fastpow(ll a,ll p,ll mod)
10 {
11     ll ans=1;
12     while(p)
13     {
14         if(p&1)ans=ans*a%mod;
15         a=a*a%mod;p>>=1;
16     }
17     return ans;
18 }
19 ll inv(ll x,ll mod){return fastpow(x,mod-2,mod);}
20 #define maxn 1000005 
21 int n;
22 ll tot,a[maxn],ans;
23 ll b[maxn],c[maxn];
24 void check(ll k)
25 {
26     ll res=0,tt=0;
27     vector<pll> v;
28     for(int i=1;i<=n;++i)b[i]=a[i]%k,tt+=b[i],c[i]=b[i];
29     ll K=tt/k;
30     int j=1;
31     for(int i=1;i<=K;++i)
32     {
33         v.clear();
34         ll sx=0,sy=0,num=0;
35         while(j<=n&&num<=k)
36         {
37             if(b[j]>0)
38             {
39                 ll tmp=min(b[j],k-num);
40                 v.push_back(mpr(j,tmp)),sy+=j*tmp,num+=tmp;
41                 b[j]-=tmp;
42             }
43             if(num==k)break;
44             j++;
45         }
46         ll t=(ll)5e18;
47         if(v.size())
48         {
49             ll s=0;
50             for(int p=0;p<v.size();++p)
51             {
52                 ll pos=v[p].first;
53                 t=min(t,1ll*pos*s-sx+sy-1ll*(k-s)*pos);
54                 sx+=pos*v[p].second;sy-=pos*v[p].second;
55                 s+=v[p].second;
56             }
57             res+=t;
58         }
59     }
60     ans=min(ans,res);
61 }
62 int main()
63 {
64     scanf("%d",&n);
65     for(int i=1;i<=n;++i)scanf("%I64d",&a[i]),tot+=a[i];
66     if(tot==1)
67     {
68         puts("-1");
69         return 0;
70     }
71     ans=(ll)5e18;
72     ll x=tot;
73     for(ll i=2;i*i<=tot;++i)if(x%i==0)
74     {
75         while(x%i==0)x/=i;
76         check(i);
77     }
78     if(x>1)check(x);
79     cout<<ans<<endl;
80 }
View Code

C.

固定1,2两个点,然后利用(n)次叉积问出其他点在((1,2))这条线的哪一侧

然后再用(n)次面积问出两边最大面积点

最后问每个点在最大面积点的哪边,然后sort一下就可以了

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 using namespace std;
 4 int n;
 5 vector<ll> A,B;
 6 ll s[1005];
 7 vector<ll> X,Y,Z,W;
 8 ll ask(ll t,ll i,ll j,ll k)
 9 {
10     ll x;
11     cout<<t<<" "<<i<<" "<<j<<" "<<k<<endl;
12     fflush(stdout);
13     cin>>x;
14     return x;
15 }
16 bool cmp1(int x,int y)
17 {
18     return s[x]<s[y];
19 }
20 bool cmp2(int x,int y)
21 {
22     return s[x]>s[y];
23 }
24 int main()
25 {
26     cin>>n;
27     for(int i=3;i<=n;++i)
28     {
29         ll x=ask(2,1,i,2);
30         if(x>0)A.push_back(i);
31         else B.push_back(i);
32     }
33     ll ida=0,sa=0,idb=0,sb=0;
34     for(ll x:A)
35     {
36         ll y=ask(1,1,x,2);
37         s[x]=y;
38         if(y>sa)ida=x,sa=y;
39     }
40     for(ll x:B)
41     {
42         ll y=ask(1,1,x,2);
43         s[x]=y;
44         if(y>sb)idb=x,sb=y;
45     }
46     for(ll x:A)if(x!=ida)
47     {
48         ll y=ask(2,1,x,ida);
49         if(y<0)Y.push_back(x);
50         else X.push_back(x);
51     }
52     for(ll x:B)if(x!=idb)
53     {
54         ll y=ask(2,1,x,idb);
55         if(y<0)W.push_back(x);
56         else Z.push_back(x);
57     }
58     sort(X.begin(),X.end(),cmp1);
59     sort(Y.begin(),Y.end(),cmp2);
60     sort(Z.begin(),Z.end(),cmp1);
61     sort(W.begin(),W.end(),cmp2);
62     cout<<0<<" ";
63     cout<<1<<" ";
64     for(ll x:X)cout<<x<<" ";
65     if(ida)cout<<ida<<" ";
66     for(ll x:Y)cout<<x<<" ";
67     cout<<2<<" ";
68     for(ll x:Z)cout<<x<<" ";
69     if(idb)cout<<idb<<" ";
70     for(ll x:W)cout<<x<<" ";
71 }
View Code

D.

考虑一种暴力做法:

对于修改操作,对点(u)枚举和他相邻的点(v),那么就是这个子树(subtree(v))加(frac{(n-size[v])}{n}*d)

然后我们考虑提出根之后就是dfs序上一段区间加,可以线段树维护

但是这个在点度数大的时候会GG

那么考虑Bigsmall

把大度数的点当做关键点,这些点不用线段树维护,暴力打标记

然后暴力爬关键点统计标记

  1 #include<bits/stdc++.h>
  2 #define ll long long
  3 #define ull unsigned long long
  4 #define pii pair<int,int>
  5 #define pll pair<long long,long long>
  6 #define mpr(a,b) make_pair(a,b)
  7 #define maxn 300005
  8 using namespace std;
  9 ll gcd(ll a,ll b){if(!b)return a;return gcd(b,a%b);}
 10 ll fastpow(ll a,ll p,ll mod)
 11 {
 12     ll ans=1;
 13     while(p)
 14     {
 15         if(p&1)ans=ans*a%mod;
 16         a=a*a%mod;p>>=1;
 17     }
 18     return ans;
 19 }
 20 ll inv(ll x,ll mod){return fastpow(x,mod-2,mod);}
 21 const ll mod = 998244353;
 22 int n,q;
 23 vector<int> g[maxn];
 24 int f[maxn],top[maxn];
 25 int lpos[maxn],rpos[maxn],cnt,sz[maxn];
 26 ll addt[maxn];
 27 const int B = 100;
 28 void dfs(int u,int fa)
 29 {
 30     if(g[fa].size()>B)top[u]=u;
 31     else top[u]=top[fa];
 32     f[u]=fa;
 33     lpos[u]=++cnt; 
 34     sz[u]=1;
 35     for(int v:g[u])if(v!=fa)
 36     {
 37         dfs(v,u);
 38         sz[u]+=sz[v];
 39     }
 40     rpos[u]=cnt;
 41 }
 42 ll val[maxn<<2];
 43 void add(int rt,int l,int r,int ql,int qr,ll v)
 44 {
 45     if(ql>qr)return;
 46     if(ql<=l&&r<=qr)
 47     {
 48         val[rt]=(val[rt]+v)%mod;
 49         return;
 50     }
 51     int mid=(l+r)>>1;
 52     if(ql<=mid)add(rt<<1,l,mid,ql,qr,v);
 53     if(qr>mid)add(rt<<1|1,mid+1,r,ql,qr,v);
 54 }
 55 ll query(int rt,int l,int r,int pos)
 56 {
 57     ll ans=val[rt];
 58     int mid=(l+r)>>1;
 59     if(l==r)return ans;
 60     if(pos<=mid)ans=(ans+query(rt<<1,l,mid,pos))%mod;
 61     else ans=(ans+query(rt<<1|1,mid+1,r,pos))%mod;
 62     return ans;
 63 }
 64 int main()
 65 {
 66     scanf("%d%d",&n,&q);
 67     for(int x,y,i=1;i<n;++i)
 68     {
 69         scanf("%d%d",&x,&y);
 70         g[x].push_back(y);
 71         g[y].push_back(x); 
 72     }
 73     dfs(1,0);
 74     while(q--)
 75     {
 76         int opt,u,d;
 77         scanf("%d",&opt);
 78         if(opt==1)
 79         {
 80             scanf("%d%d",&u,&d);
 81             add(1,1,n,1,lpos[u]-1,1ll*sz[u]*inv(n,mod)%mod*d%mod);
 82             add(1,1,n,rpos[u]+1,n,1ll*sz[u]*inv(n,mod)%mod*d%mod);
 83             if(g[u].size()>B)addt[u]=(addt[u]+d)%mod;
 84             else
 85             {
 86                 for(int v:g[u])if(v!=f[u])
 87                 {
 88                     add(1,1,n,lpos[v],rpos[v],1ll*(n-sz[v])*inv(n,mod)%mod*d%mod);
 89                 }
 90                 add(1,1,n,lpos[u],lpos[u],d);
 91             }
 92         }
 93         else
 94         {
 95             scanf("%d",&u);
 96             ll ans=(addt[u]+query(1,1,n,lpos[u]))%mod; 
 97             while(top[u])
 98             {
 99                 u=top[u];
100                 ans=(ans+1ll*(n-sz[u])*inv(n,mod)%mod*addt[f[u]]%mod)%mod;
101                 u=f[u];
102             }
103             printf("%I64d
",ans);
104         }
105     }
106 }
View Code
原文地址:https://www.cnblogs.com/uuzlove/p/11896865.html