赞
踩
题目大意:给定一个序列,能够交换任意两个数的正负性,问能否构造出不递减
方法: 负数必须是连续出现在前段,正数连续出现在后段。即构造出的序列是先负数后正数。
代码:
- #include<iostream>
-
- using namespace std;
-
- const int N=100010;
- int p[N];
-
- int main()
- {
- cin.tie(0);
- cout.tie(0);
- ios::sync_with_stdio(0);
-
- int t;cin>>t;
- while(t--)
- {
- int n;
- cin>>n;
- int cntn=0;
- for(int i=1;i<=n;i++)
- {
- int x;
- cin>>x;
- p[i]=abs(x);
- if(x<0)cntn++;
- }
- bool flag=true;
- for(int i=1;i<=n;i++)
- {
- if(cntn)
- {
- cntn--;
- p[i]=-p[i];
- }
- if(i-1)
- {
- if(p[i-1]>p[i])
- {
- flag=false;
- break;
- }
- }
- }
- if(flag)
- {
- cout<<"YES"<<endl;
- }else
- {
- cout<<"NO"<<endl;
- }
- }
- return 0;
- }
题目大意:给定一个小写字母序列,再给若干个特殊的字母,每次操作,可以将序列中特殊字母的前一个字母删除。问删到不能删的时候,操作了几次
方法: 对于序列中出现的第一个特殊字母,它的操作数是前面的字母数;
对于前有特殊字母的特殊字母,它的操作数是(1+特殊字母之间的字母数)
这个1是当删到特殊字母连续的时候,删一次就可以使开端只剩一个特殊字母。
然后将所有操作数取最大值
代码:
- #include<iostream>
- #include<cstring>
- #include<vector>
-
- using namespace std;
-
- const int N=200010;
- char a[N];
- bool st[26];
- int main()
- {
- int t;
- cin>>t;
- while(t--)
- {
- memset(st,false,sizeof st);
- vector<int> ans;
- int n;
- cin>>n;
- cin>>a+1;
- int k;cin>>k;
- for(int i=1;i<=k;i++)
- {
- char c;cin>>c;
- st[c-'a']=true;
- }
- int cnt1=0;
- int cnt2=0;
- for(int i=1;i<=n;i++)
- {
- if(st[a[i]-'a'])
- {
- ans.push_back(cnt1+cnt2);
- cnt2=1;
- cnt1=0;
- }else
- {
- cnt1++;
- }
- }
- int res=0;
- for(auto x:ans)
- {
- res=max(res,x);
- }
- cout<<res<<endl;
- }
- return 0;
- }
题目大意:给定2个全排列a,b。 再给一个需要构造的全排列c。
c[i]不是0:c[i]要么为a[i]要么为b[i],
c[i]是0,那么就可以任取a[i]或b[i]。
现在问能构造符合条件的全排列c的数字。
方法: 对于确定值的c[i],不用考虑。不确定的就话,如果可以使对应所有的a[i],b[i]成一个圈,那么就有两种情况,即答案乘2。
注意:如果对于任选的a[i],b[i](c!=0)在确定的a[i],b[i](c==0)出现过,说明不能任选,那么就构不成一个圈。
代码:
- #include<iostream>
- #include<cstring>
- #include<map>
- using namespace std;
- const int N=100010;
- const int mod=1e9+7;
- typedef pair<int,int> PII;
- int a[N],b[N];
- int p[N];
- bool st[N];
- bool v[N];
-
- int main()
- {
- cin.tie(0);
- cout.tie(0);
- ios::sync_with_stdio(0);
- int t;cin>>t;
- while(t--)
- {
- memset(v,false,sizeof v);
- memset(st,false,sizeof st);
-
- int n;
- cin>>n;
-
- for(int i=1;i<=n;i++)
- {
- cin>>a[i];
- }
- for(int i=1;i<=n;i++)
- {
- cin>>b[i];
- }
-
- for(int i=1;i<=n;i++)
- {
- int c;
- cin>>c;
- if(c)
- {
- st[a[i]]=true;
- st[b[i]]=true;
- }
- }
-
- for(int i=1;i<=n;i++)
- {
- p[a[i]]=b[i];
- }
-
- long long res=1;
- for(int i=1;i<=n;i++)
- {
- if(!v[i])
- {
- int j=i;
- int cnt=0;
- bool flag=false;
- while(!v[j])
- {
- v[j]=true;
- flag|=st[j];
-
- j=p[j];
- cnt++;
- }
-
- if(cnt!=1&&!flag)
- {
- res*=2;
- res%=mod;
- }
- }
- }
- cout<<res<<endl;
- }
- return 0;
- }
题目大意:给定一个无限大的六边形网格区域(蜂窝吗),每次可以画一条直线。
直线有三种情况:与x轴平行,夹60°,夹120°
这些直线相互之间和网格之间可以形成等边三角形。
现给定得到的三角形数量,问最少画了多少根直线
方法: 规律:每次加一根直线,最多可以增加另外两种直线数量和的二倍。
预处理出直线数所能构造出的最多三角形数。
然后二分。
代码:
代码1:找到规律后发现每一轮(加三根不同直线)会多产生12个三角形。
- #include<iostream>
- using namespace std;
-
- int main()
- {
- long long res=0;
- long long temp=0;
- for(int i=0;res<=1e9;i++)
- {
- cout<<i<<" "<<3*i<<" "<<res<<endl;
- temp+=12;
- res+=temp;
- }
- //12909 38727 999853686
- return 0;
- }
代码2:
- #include<iostream>
- #include<cstring>
- #include<cstdio>
-
- using namespace std;
- const int N=40000;
- int res[N];
- int main()
- {
- int t;cin>>t;
- res[1]=0;res[2]=2;res[3]=6;
- int cnt[3]={1,1,1};
- for(int i=4;i<=38730;i++)
- {
- int j=i%3;
- int temp=0;
- for(int k=0;k<3;k++)
- {
- if(k!=j)
- {
- temp+=cnt[k]*2;
- }
- }
- cnt[j]++;
- res[i]=res[i-1]+temp;
- }
- while(t--)
- {
- int n;cin>>n;
- int l=1,r=38730;
- while(l<r)
- {
- int mid=l+r>>1;
- if(res[mid]>=n)
- {
- r=mid;
- }else
- {
- l=mid+1;
- }
- }
- cout<<r<<endl;
- }
- return 0;
- }
题目大意:一颗有n个点的树,边和点都有权值,是[1,2n-1]的全排列,找到一个根节点,使从根节点开始最大路径值最小。
方法: 参考于https://zhuanlan.zhihu.com/p/510465004
讲的挺好的,是大佬%%%%
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。