1006 Football Games
题意:
每组球队中有若干个队伍,每两个队伍之间比赛,胜得2分,负得0分,平局得1分;
然后判断题目给出的每组队伍得分是否合理,若合理输出“T”,否则输出“F”
思路:
据聚聚说是Landau's Theorem(兰道定理),弱渣表示数学定理什么的无能为力……
是这样的,我们判断得分是否合理,那么也就是说得分不能超过合理分数;
一共n个球队得分,先进行排序,可以发现如下规律(兰道定理)
1、总分一定等于n(n-1),
2、第i个分数>=i(i-1)
注意所有球队的总分加一起可能很大,用__int64
注意这句话 "Multiple test cases, process till end of the input." 看仔细怎么输入
还有时间超限很多次,为啥呢,因为arr数组开太小,一定仔细看N的范围是啥呀……
代码:
#include <iostream>
#include <stdio.h>
#include <algorithm>
using namespace std;
//const int N = 100+5;
const int N = 20000+10;
__int64 arr[N];
int main(){
int t, m;
//scanf("%d", &t);
//while(t-->0){
while(~scanf("%d", &t))
while(t-->0){
int ans=0, flag=1;
scanf("%d", &m);
for(int i=0; i<m; i++){
scanf("%I64d", &arr[i]);
ans += arr[i];
}
if(ans!=m*(m-1) || m<=1){
printf("F\n");
continue;
}
ans = 0;
sort(arr, arr+m);
for(int i=0; i<m; i++){
ans += arr[i];
if(ans < i*(i+1)){
flag = 0;
break;
}
}
/*
if(flag) {printf("T\n"); continue;}
printf("F\n");
*/
printf(flag?"T\n":"F\n");
}
return 0;
}
1007 Friends and Enemies
题意:
n个人m种颜色,每两个人之间必然存在朋友或敌人任一关系。如果两人是朋友,那么这两人的项链中至少有一块石头颜色相同;如果两人是敌人,那么这两人的项链中没有相同颜色的石头,我们要求的是n个人中每两人任意关系,如果项链需要的颜色都<=m, 输出“T”,否则输出“F”,注意项链可以为空
思路:
n个点的图,要求有尽量多的边,并且不存在三元环,这个边数就是m的下界
对于一个n个结点的没有三元环的图,边数最大的就是完全二分图
于是答案就是(n/2 * ((n+1)/2))
代码:
#include <iostream>
#include <stdio.h>
#include <algorithm>
using namespace std;
int main(){
int n, m;
while(~scanf("%d%d", &n, &m)){
//注意运算的优先顺序
if((n/2) * ((n+1)/2) <= m){
printf("T\n");
continue;
}
printf("F\n");
}
return 0;
}
1008 Function
题意:
给你一串数字,然后进行查询操作,输入l和r,代表查询区间[l,r],求F(l,r), f[l,r]的函数表达式如下
F(l,r)={AlF(l,r−1) modArl=r;l<r.
思路:
用线段树维护区间最小值
遇到比arr[l]大的掠过,<=其的就取余%
最重要的是查询过程,返回的是>=arr[l]的最小下标
总之,如果能进子树(说明有比val小的值存在),左子树找的到就return 下标
左子树找不到(说明最小值所在下标不在范围内),再进右子树,右子树找的到就return 下标
如果右子树中最小值所在下标不在范围内,那么结束了,return -1
其实就是如果你找一个区间最小值,这个最小值不在你问询的范围内,那么结束return -1; 如果能找到就返回下标
代码:
#include <stdio.h>
#include <string.h>
#include <iostream>
#include<vector>
#define inf 0x7f7f7f7f
#define lson root<<1,left,mid
#define rson root<<1|1,mid+1,right
using namespace std;
/*
线段树维护区间最小值
遇到比之小的掠过,>=其的就取余%
*/
const int N = 1e5+5;
int arr[N];
struct{
int val;
int l;
int r;
}Tree[N*4];
int my_min(int x, int y){
return x<y?x:y;
}
int pushup(int root){
return my_min(Tree[root<<1].val, Tree[root<<1|1].val);
}
void build(int root, int left, int right){
Tree[root].l = left;
Tree[root].r = right;
if(left == right){
Tree[root].val = arr[left];
return;
}
int mid = (left+right) >> 1;
build(lson);
build(rson);
Tree[root].val = pushup(root);
}
//返回的是>=arr[l]的最小下标
/*
int query(int root, int ql, int qr, int val){//查询[ql,qr]
if(ql>Tree[root].r || qr<Tree[root].l)//说明[ql,qr]不会涉及此root
return ql+1;//0<=a[i]<=1e5
if(ql<=Tree[root].l && qr>=Tree[root].r){
if(Tree[root].val < val) return Tree[root].r;
}
if(Tree[root<<1].val < val)
return query(root<<1, ql, qr, val);
else
return query(root<<1|1, ql, qr, val);
}
*/
int query(int root, int ql, int qr, int val){
if(Tree[root].l == Tree[root].r){
if(Tree[root].val <= val) return Tree[root].r;
return -1;
}
//如果root左子树可进,那么进
if(ql<=Tree[root<<1].r && val>=Tree[root].val){
//如果root左子树可以找到,那么return
int tmp = query(root<<1, ql, qr, val);
if(tmp != -1) return tmp;
//如果root左子树不能找到,那么肯定在root右子树,还是进右子树
if(qr>=Tree[root<<1|1].l && val>=Tree[root].val)
return query(root<<1|1, ql, qr, val);
}
//如果root右子树可进,那么进
if(qr>=Tree[root<<1|1].l && val>=Tree[root].val)
return query(root<<1|1, ql, qr, val);
return -1;
}
int main(){
int t, n, m;
int l, r;
scanf("%d", &t);
while(t-->0){
scanf("%d", &n);
for(int i=1; i<=n; i++)
scanf("%d", &arr[i]);
build(1,1,n);
scanf("%d", &m);
while(m-->0){
scanf("%d%d", &l, &r);
int ans = arr[l];
l++;
while(l <= r){
l = query(1,l,r,ans);
if(l == -1) break;
ans %= arr[l];
}
printf("%d\n", ans);
}
}
return 0;
}
/*
1
5
3 4 2 9 3
1
1 4
----------
1
*/
反思:
真的写这道题的时候仿佛一个智障……整个脑子都被搅乱了,真的是……vegetable
1009 Sparse Graph
题意:
给一个无向图和源点s,求在补图中源点s到其他点的最短距离,如果到其他点不通的话输出“-1”
思路:
补图求最短路
代码:
#include<cstdio>
#include<cstring>
#include<queue>
#include<set>
#include<algorithm>
using namespace std;
const int N = 200000+5;
const int M = 5500+5;
const int inf = 1<<29;
typedef long long LL;
int head[N];
int dis[N];
bool vis[N];
struct Edge{
int v;
int c;
int next;
}edge[N<<1];
int p = 0;
void add(int u,int v)
{
edge[p].v = v;
edge[p].c = inf;
edge[p].next = head[u];
head[u] = p++;
}
struct node{
int v,c;
node(int _v,int _c){
v = _v;
c = _c;
}
bool operator < (const node &a) const{
return c > a.c;
}
};
void BFS(int n, int s)
{
queue<int>Q;
Q.push(s);
dis[s] = 0;
//dis[n] = inf;
//fill(dis+1, dis+n+1, inf);
set<int>sa, sb;
for(int i=1; i<=n; i++)
if(i != s)
sa.insert(i);
while(!Q.empty())
{
int Now = Q.front();
Q.pop();
for(int i=head[Now]; i!=-1; i=edge[i].next){
int New = edge[i].v;
if(!sa.count(New)) continue;
sa.erase(New);
sb.insert(New);
}
for(set<int>::iterator it=sa.begin(); it!=sa.end(); it++){
Q.push(*it);
dis[*it] = dis[Now] + 1;
}
sa.swap(sb);
sb.clear();
}
}
int main()
{
int t, n, m, s;
int u, v;
scanf("%d", &t);
while(t-->0){
scanf("%d%d", &n, &m);
p=0;
memset(head,-1,sizeof head);
memset(vis,false,sizeof vis);
memset(dis, 0, sizeof(dis));
for(int i=0; i<m; i++){
scanf("%d%d",&u, &v);
add(u, v);
add(v, u);
}
scanf("%d", &s);
BFS(n, s);
for(int i=1; i<=n-2; i++){
if(i != s){
if(dis[i] == 0)
dis[i] = -1;
printf("%d ", dis[i]);
}
}
if(s==n)
printf("%d\n", dis[n-1]);
else if(s==n-1){
if(dis[n] == 0)
dis[n] = -1;
printf("%d\n", dis[n]);
}
else{
if(dis[n-1] == 0)
dis[n-1] = -1;
if(dis[n] == 0)
dis[n] = -1;
printf("%d %d\n", dis[n-1], dis[n]);
}
}
return 0;
}
/*
3
5 7
1 2
1 3
1 5
2 3
3 4
3 5
4 5
1
4 1
1 2
1
2 0
1
---
2 -1 1 3
2 1 1
1
*/
1010 Weak Pair
思路:
是树状数组/线段树,写不出来,功力太浅,等多几个树状数组找找感觉再回来做_(:зゝ∠)_