爆炸场,A被hack两次,a,c都看错题意。。。还是太菜了
A水题,ifelse写的太搓了被hack。。
#include<bits/stdc++.h> #define fi first #define se second #define mp make_pair #define pb push_back #define pii pair<int,int> #define C 0.5772156649 #define pi acos(-1.0) #define ll long long #define mod 1000000007 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 using namespace std; const double g=10.0,eps=1e-7; const int N=500000+10,maxn=sqrt(N)+10,inf=0x3f3f3f; int main() { ios::sync_with_stdio(false); cin.tie(0); int n,a,b,c; cin>>n>>a>>b>>c; n--; if(n==0)cout<<0<<endl; else { if(c<=a&&c<=b)cout<<(n-1)*c+min(a,b)<<endl; else { cout<<n*min(a,b)<<endl; } } return 0; } /******************** ********************/
B也是瞎搞,找间距是k的倍数,直接取模计数
#include<bits/stdc++.h> #define fi first #define se second #define mp make_pair #define pb push_back #define pii pair<int,int> #define C 0.5772156649 #define pi acos(-1.0) #define ll long long #define mod 1000000007 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 using namespace std; const double g=10.0,eps=1e-7; const int N=100000+10,maxn=sqrt(N)+10,inf=0x3f3f3f; int a[N]; map<int,int>b; int main() { ios::sync_with_stdio(false); cin.tie(0); int n,m,k; cin>>n>>k>>m; for(int i=0;i<n;i++) { cin>>a[i]; b[a[i]%m]++; } int id=-1; for(int i=0;i<m;i++) { if(b[i]>=k) { id=i; break; } } if(id>=0) { cout<<"Yes"<<endl; vector<int>v; for(int i=0;i<n;i++) { if(a[i]%m==id) v.pb(a[i]); } for(int i=0;i<k;i++)cout<<v[i]<<" "; cout<<endl; } else cout<<"No"<<endl; return 0; } /******************** ********************/
C找十进制每一位加到自身等于一个数,直接枚举1到81,用n挨个减,判断就好了
#include<bits/stdc++.h> #define fi first #define se second #define mp make_pair #define pb push_back #define pii pair<int,int> #define C 0.5772156649 #define pi acos(-1.0) #define ll long long #define mod 1000000007 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 using namespace std; const double g=10.0,eps=1e-7; const int N=100000+10,maxn=sqrt(N)+10,inf=0x3f3f3f; int main() { ios::sync_with_stdio(false); cin.tie(0); int n; cin>>n; vector<int>v; for(int i=1;i<=81;i++) { int sum=0,s=n-i; while(s) { sum+=s%10; s/=10; } if(sum==i)v.pb(n-i); } sort(v.begin(),v.end()); cout<<v.size()<<endl; for(int i=0;i<v.size();i++) cout<<v[i]<<endl; return 0; } /******************** ********************/
D题意:每次把第i位放一个东西,操作要求把所有的东西放到最后。解法:遍历一遍,同时维护一个最后一位输出就好了
#include<bits/stdc++.h> #define fi first #define se second #define mp make_pair #define pb push_back #define pii pair<int,int> #define C 0.5772156649 #define pi acos(-1.0) #define ll long long #define mod 1000000007 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 using namespace std; const double g=10.0,eps=1e-7; const int N=300000+10,maxn=sqrt(N)+10,inf=0x3f3f3f; int s[N]; int main() { ios::sync_with_stdio(false); cin.tie(0); int n,cnt; cin>>n; cnt=n; cout<<1<<" "; for(int i=1;i<=n;i++) { int a; cin>>a; s[a]++; if(a==cnt) { while(cnt>0&&s[cnt])cnt--; } cout<<cnt-n+i+1<<" "; } return 0; } /******************** ********************/
E题意:有n个类似字符串a,A的东西,然后刚开始是小写,可以把某几个改成大写,要求最后结果是按字符串递增的
题解:用一个数组维护不能改变的数,还有一个维护已经改变的数,用vector存必须同时改变的数,当需要改变时dfs容器,看有没有产生冲突,每两个字符串找第一个不相同的字符,此时只有八种情况,挨个枚举就行了,分别是(1,2)(1‘,2)(1,2’)(1‘,2’)(2,1)(2’,1)(2,1‘)(2’,1‘)
#include<bits/stdc++.h> #define fi first #define se second #define mp make_pair #define pb push_back #define pii pair<int,int> #define C 0.5772156649 #define pi acos(-1.0) #define ll long long #define mod 1000000007 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 using namespace std; const double g=10.0,eps=1e-7; const int N=100000+10,maxn=sqrt(N)+10,inf=0x3f3f3f; bool ca[N],no[N],f; int sz[N]; vector<int>s[N]; vector<int>v[N]; void dfs(int u) { if(no[u]) { f=1; return ; } else ca[u]=1; for(int i=0;i<v[u].size()&&!f;i++) { dfs(v[u][i]); } } void fuck(int p1,int p2) { if(p1>p2) { if(!ca[p1]&&!ca[p2]) { f=0; dfs(p1); if(f) { puts("No"); exit(0); } else no[p2]=1; } else if(ca[p1]&&!ca[p2]) { no[p2]=1; } else { puts("No"); exit(0); } } else { if(!ca[p1]&&ca[p2]) { f=0; dfs(p1); if(f) { puts("No"); exit(0); } } else if(!ca[p1]&&!ca[p2]) { v[p2].pb(p1); } } } int main() { int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d",&sz[i]); s[i].clear(); for(int j=0;j<sz[i];j++) { int a; scanf("%d",&a); s[i].pb(a); } } for(int i=2;i<=n;i++) { if(s[i]==s[i-1])continue; else if(sz[i-1]>sz[i]) { bool ok=1; for(int j=0;j<s[i].size();j++) { if(s[i-1][j]!=s[i][j]) { fuck(s[i-1][j],s[i][j]); ok=0; break; } } if(ok) { puts("No"); return 0; } } else if(sz[i-1]<=sz[i]) { for(int j=0;j<s[i-1].size();j++) { if(s[i-1][j]!=s[i][j]) { fuck(s[i-1][j],s[i][j]); break; } } } } puts("Yes"); v[0].clear(); for(int i=1;i<=m;i++) if(ca[i]) v[0].pb(i); printf("%d ",v[0].size()); for(int i=0;i<v[0].size();i++) printf("%d ",v[0][i]); puts(""); return 0; } /******************** ********************/
E还可以用2-sat做,每次遇到不同的字符就找冲突关系来建图,当遇到不同时,我们用a,b,a',b'代替,如果a<b,那么当选择a时,那么应该取a'来构成冲突,同理取b'时应该取b,如果a>b,那么选b'时只能选择a,选a时只能选择b',这样构图之后跑一边tarjan,因为tarjan拍好之后拓扑序是反的,所以输出拓扑序大的那一个,因为拓扑序大 的那一个不会有入度,不会与其他强连通分量构成冲突
#include<bits/stdc++.h> #define fi first #define se second #define mp make_pair #define pb push_back #define pii pair<int,int> #define C 0.5772156649 #define pi acos(-1.0) #define ll long long #define mod 1000000007 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 using namespace std; const double g=10.0,eps=1e-7; const int N=400000+10,maxn=100000+10,inf=0x3f3f3f; int dfn[N],low[N]; int inans[N],ins[N],ans[N]; stack<int>s; int num,index,n,m; vector<int>v[N],p[N]; void tarjan(int u) { ins[u]=2; dfn[u]=low[u]=++index; s.push(u); for(int i=0;i<v[u].size();i++) { int x=v[u][i]; if(!dfn[x]) { tarjan(x); low[u]=min(low[u],low[x]); } else if(ins[x]==2)low[u]=min(low[u],dfn[x]); } if(dfn[u]==low[u]) { ++num; while(!s.empty()) { int k=s.top(); s.pop(); ins[k]=1; inans[k]=num; if(u==k)break; } } } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { int a; scanf("%d",&a); p[i].clear(); for(int j=0;j<a;j++) { int k; scanf("%d",&k); p[i].pb(k); } } num=index=0; for(int i=2;i<=n;i++) { if(p[i]==p[i-1])continue; if(p[i-1].size()>p[i].size()) { bool ok=0; for(int j=0;j<p[i].size();j++) { if(p[i-1][j]!=p[i][j]) { int p1=p[i-1][j],p2=p[i][j]; if(p1>p2) { // cout<<p1<<" "<<p2+m<<endl; // cout<<p2+m<<" "<<p1<<endl; v[p1].pb(p1+m); v[p2+m].pb(p2); } else { // cout<<p1<<" "<<p2<<endl; // cout<<p2+m<<" "<<p1+m<<endl; v[p1].pb(p2); v[p2+m].pb(p1+m); } ok=1; break; } } if(!ok) { cout<<"No"<<endl; return 0; } } else { for(int j=0;j<p[i-1].size();j++) { if(p[i-1][j]!=p[i][j]) { int p1=p[i-1][j],p2=p[i][j]; if(p1>p2) { // cout<<p1<<" "<<p2+m<<endl; // cout<<p2+m<<" "<<p1<<endl; v[p1].pb(p1+m); v[p2+m].pb(p2); } else { // cout<<p1<<" "<<p2<<endl; // cout<<p2+m<<" "<<p1+m<<endl; v[p1].pb(p2); v[p2+m].pb(p1+m); } break; } } } } for(int i=1;i<=2*m;i++) if(!dfn[i]) tarjan(i); for(int i=1;i<=m;i++) { if(inans[i]==inans[i+m]) { cout<<"No"<<endl; return 0; } } cout<<"Yes"<<endl; int res=0; for(int i=1;i<=m;i++) if(inans[i]>inans[i+m]) res++; printf("%d ",res); for(int i=1;i<=m;i++) if(inans[i]>inans[i+m]) printf("%d ",i); puts(""); return 0; } /******************** 6 5 2 1 2 2 1 2 3 1 2 3 2 1 5 2 4 4 2 4 4 ********************/
F:题意:有一组数,找区间l,r全部或起来的值大于区间最大值的区间个数
题解:用总数-不能取的区间,对于不能减的区间我们可以用一个l数组一个r数组来维护,l[i]代表i不能取的区间到最左端的最远距离,r同理,这样结果关于这一个点不能取的区间种数就是(i-l[i])*(r[i]-i)
计算l数组时,我们必须要用一个map来维护,因为如果一个区间里有两个相同的值时,我们会减两次,那么用map记录每次i的位置,对l赋初值时,赋map对应的值,因为l已经排除了重复的情况,所以r不用重复的去重,直接反向算就好了
#include<bits/stdc++.h> #define fi first #define se second #define mp make_pair #define pb push_back #define pii pair<int,int> #define C 0.5772156649 #define pi acos(-1.0) #define ll long long #define mod 1000000007 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 using namespace std; const double g=10.0,eps=1e-7; const int N=500000+10,maxn=10000+10,inf=0x3f3f3f; int a[N],l[N],r[N],pos[32]; map<int,int>last; int main() { int n; scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&a[i]); for(int i=1;i<=n;i++) { l[i]=last[a[i]]; for(int j=0;j<32;j++) if((a[i]&(1<<j))==0) l[i]=max(l[i],pos[j]); for(int j=0;j<32;j++) if((a[i]&(1<<j))>0) pos[j]=i;//最后出现的第j位是1的那个数 last[a[i]]=i; } for(int i=0;i<32;i++)pos[i]=n+1; for(int i=n;i>=1;i--) { r[i]=n+1; for(int j=0;j<32;j++) if((a[i]&(1<<j))==0) r[i]=min(r[i],pos[j]); for(int j=0;j<32;j++) if((a[i]&(1<<j))>0) pos[j]=i; } ll ans=(ll)n*(n+1)/2; for(int i=1;i<=n;i++) { ll t1=i-l[i],t2=r[i]-i; ans-=t1*t2; } printf("%lld ",ans); return 0; } /******************** ********************/