地址: http://codeforces.com/contest/1156
做了前3题,好不容易可以上分,结果不评分,有点难受。。
A. Inscribed Figures
思路:题目有点长。。,然后看了一半就直接看样例了(还是样例容易看懂),wa了一次,注意 3-1-2的情况有一个点是重合了
Code:
#include
#include
using namespace std;
const int MAX_N=2e5+5;
int n,m,T;
int a[MAX_N];
int d[5][5];
int main()
{
ios::sync_with_stdio(false);
d[1][2]=3; d[1][3]=4;
d[2][1]=3; d[2][3]=-1;
d[3][1]=4; d[3][2]=-1;
cin>>n;
for(int i=0;i>a[i];
int ans=0;
for(int i=1;i=2&&a[i-2]==3&&a[i-1]==1&&a[i]==2) --ans;
ans+=d[a[i-1]][a[i]];
}
if(ans!=-1){
cout<<"Finite"<
B. Ugly Pairs
思路:构造题。开始题目看错了,以为相同的字符相邻是不可以的,写了半天没写出来,然后一看题目列表已经过了600多了,就觉得奇怪,应该没这么难,然后看样例就发现相同字符相邻是可以的QAQ. 这样的话就只要对不同的字符进行构造即可,然后改了下先前写的代码就ok了。。大体思路是从两端交替摆放。最后判断有多少个非法摆放,若小于1个则从非法处拆开再首位合并起来即可。
Code:
#include
#include
#include
#include
using namespace std;
typedef long long LL;
int n,T;
int d[30];
char res[105];
string str;
int main()
{
ios::sync_with_stdio(false);
cin>>T;
while(T--){
memset(d,0,sizeof(d));
cin>>str;
n=str.length();
for(int i=0;il&&!d[r]){
--r;
}
if(l==r) break;
if(d[l]){
res[s++]=char(l+'a');
++l;
}
if(d[r]){
res[s++]=char(r+'a');
--r;
}
}
if(l==r&&d[l]){
res[s++]=char(l+'a');
}
int boo=0;
l=0;
if(abs(res[0]-res[s-1])==1) ++boo;
for(int i=1;i
C. Match Points
思路:贪心。比赛时是做了A(后来重测wa了。。)之后看题目发现C过的也挺多的,然后看下C就发现这题我做过啊,然后刷刷刷的就一遍过了^v^. 这题用贪心思路,先由小到大排序,在看要找的[l,r]都是一对对的,因此最多找到n/2个,因此将数组对半分,l从左半边开始,r从右半边开始找,每次用r去匹配l即可
Code:
#include
#include
using namespace std;
typedef long long LL;
const int MAX_N=2e5+5;
int n,m,T;
int a[MAX_N];
int main()
{
ios::sync_with_stdio(false);
cin>>n>>m;
for(int i=0;i>a[i];
sort(a,a+n);
int ans=0;
int l=0,h=n/2,r=h;
while(l=m){
++ans; ++l;
}
++r;
}
cout<
D. 0-1-Tree
思路:树状DP。对每个节点作为路线的起点分析。假定1节点为整个树的根节点。首先DFS一遍找到以每个节点为根节点的树的d0[i],d1[i],d2[i]的数量。其中
d0[i]:以i节点为根节点的树中,从根节点出发路径权值都是0的路径数。
d1[i]:以i节点为根节点的树中,从根节点出发路径权值都是1的路径数。
d2[i]:以i节点为根节点的树中,从根节点出发路径权值开始是1后来是0的路径数。
在DFS一遍求出以每个节点为起点的合法路径数Si。而显然Si=d0[i]+d1[i]+d2[i]。但是这里的d0[i],d1[i],d2[i]应该是以i节点为整个树的根节点,而第一次DFS求的是以1节点为整个树的根节点下的 i节点的树。因此求Si时,需要将i节点的父亲节点的d0,d1,d2转移到 i节点上来,而这个转移则可通过 i节点和其父亲节点的连接线的权值w来分类讨论即可
Code:
#include
#include
#include
using namespace std;
typedef long long LL;
typedef pair pr;
const int MAX_N=2e5+5;
int n;
LL ans;
LL d0[MAX_N],d1[MAX_N],d2[MAX_N];
vector e[MAX_N];
/*
对每个点作为起点分析QAQ
*/
void DFS(int u,int pre);
void DFS1(int u,int pre);
int main()
{
ios::sync_with_stdio(false);
cin>>n;
int u,v,w;
for(int i=1;i>u>>v>>w;
e[u].push_back({v,w});
e[v].push_back({u,w});
}
DFS(1,0);
DFS1(1,0);
cout<
E. Special Segments of Permutation
思路:二分+set
题目要求区间[l,r]中 a[l]+a[r]=max(a[l-->r]),对max{a[i]}继续分析,可以看出关键点max{a[i]},即最大值是影响到比它小的值的求解的。那么对a[l]+a[r]=a[i]的a[i]由大到小进行遍历,对于a[i]的区间边界l,r求解,肯定是包含a[i]且比a[i]大的点组成的边界,用d[i]记录值为i的点的下标值。这个可以用set自带的排序+二分查找来找到l,r.再求a[i]的解时,可以遍历[l,r]中离a[i]点近的一边x,再判断a[i]-x是否在另一边即可。在处理完a[i],在将a[i]点所处的位置下标加入set即可
Code:
#include
#include
#include
using namespace std;
typedef long long LL;
const int MAX_N=2e5+5;
int n;
LL ans;
int a[MAX_N],d[MAX_N];
set iset;
void Find(int p,int l,int r);
int main()
{
ios::sync_with_stdio(false);
cin>>n;
for(int i=1,x;i<=n;++i)
{
cin>>a[i];
d[a[i]]=i;
}
iset.insert(0);
iset.insert(n+1);
int l,r;
set::iterator f;
for(int i=n;i>=3;--i)
if(d[i]>1&&d[i]0&&d[p-a[i]]>h&&d[p-a[i]]<=r) ++ans;
}else{
for(int i=h+1;i<=r;++i)
if(p-a[i]>0&&d[p-a[i]]>=l&&d[p-a[i]]