North American Invitational Programming Contest 2018

题目链接:https://nanti.jisuanke.com/?kw=The%20North%20American%20Invitational%20Programming%20Contest%202018

本博客参考了(抄了)巨佬Claris的博客 https://www.cnblogs.com/clrs97/p/8730429.html,但是因为Claris太巨了,每道题就几句话完事了,我结合自己的理解补充了一下,部分由于自己的菜,暂时还不会,留着以后补。

A-Cut it out

本题是结合一部分计算几何的DP,等我学会计算几何(xia bei zi)再说吧··

B-Double Clique

题意

给出一个n个结点m条边的无向图G,点集是V,边集是E。G‘是G的补集。一个图的补集中的点和原图中的点相同,但是所有原图中没有的边补集中都有,原图中有的边补集中没有。 Clique是点的子集,且任意两点之间都有一条边,一个结点的子集和S被称为Double Clique当且仅当,S在图G中是clique,且V-S在G’中是clique。注意,一个空的结点集合也被认为是clique。给出一个图,计算double clique在图中的数量。

分析

首先给出一个结论:一个方案合法当且仅当 团点数*(团点数-1)+独立集度数和=团度数和 。

为什么呢,我们来想一下,前i个点是原图中能构成团的点,i+1到n个点是补图中能构成团的点(独立集),前i个点每个点至少都和团中其他所有点都有边相连,这些度数为i*(i-1),还可能有一些边连向独立集中一些点的边,而独立集内部是没有互相连得边的,所以团中连入独立集的边等于独立集中度数的和。

然后我们通过上面这个结论找出一个合法的方案以后,然后要么从团中拿出一个点放到独立集中,要么从独立集中拿出一个点放进团中,要么是从两边各拿出一个点交换。前面两种很好理解,因为如果团中两个点放到独立集中,独立集就不是独立集了(团中点相互连着边)。关键是最后的交换怎么交换。我们想团和独立集中的点交换的条件是什么?i是团内点的数量,n-i+1是独立集中点的数量。如果团内度数最少的点的度数是i-1,那么这个点可以和独立集中度数为i-1的点进行交换。如果团内度数最少的点的度数为i,那么就说明这个点有一条边是连向独立集,那么这些点可以跟独立集内度数为i的点交换。如果团内度数最少的点度数大于i,那么久说明最少的这个点也有两条以上的边连向独立集,这时候没有可以交换的点,因为此时团内任何一个点和独立集交换,独立集内都有边了。

代码可以去看Claris老师的呦~

C-Flashing Fluorescents

题意

你有n个灯,每个灯都有一个按钮,排成一排。按下一个开关将会改变灯泡状态。灯泡改变需要一秒钟(时间步长),你可以在任何一个时间按下一个按钮,但是它会在下一秒起作用。在每一秒前,你都可以选择并按下一个按钮。灯的开关具有传递性。 即第i秒前如果按下开关j,那么i秒灯泡j状态发生变化,i+1秒,j+1灯泡发生变化,i+2秒,j+2灯泡发生变化。可以相互抵消。给出初始状态,问最少需要多少秒可以打开所有的灯 最多有16的灯泡和开关。

分析

个人感觉这个题特别巧妙。f[now][S]是在now步内,能否走到S状态。我们可以反着想,当第now秒的时候,最长的那一段走了now长(从第一秒开始走的状态),然后第二秒开始走的状态最长走了now-1秒。然后理解了按照那个递推式暴力枚举转移就好惹。

D-D. Missing Gnomes

 签到题

E- Prefix Free Code

题意

这个题就是拿trie+树状数组就可以,并不是很难。因为题目保证给出的单词中没有哪个是另一个的前缀, 所以我们可以很轻松的用trie给单词排序并且可以通过trie来找出单词,树状数组维护的是是出现过的小于的单词有多少个。

哈哈这个题有代码了,但是好几天前写的了所以解析写的不够详细有疑问的可以加QQ(好了好了我知道我博客没人看)

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <iostream>
  4 #include <algorithm>
  5
  6 using namespace std;
  7 typedef long long LL;
  8 const int maxn=1000000+20;
  9 const int mod=1e9+7;
 10 int n,k;
 11 LL A[maxn];
 12
 13 int ch[maxn][26],val[maxn],sz;
 14 void insert(char *s,int v){
 15     int len=strlen(s),u=0;
 16     for(int i=0;i<len;i++){
 17         int c=s[i]-‘a‘;
 18         if(!ch[u][c]){
 19             ch[u][c]=sz;
 20             memset(ch[sz],0,sizeof(ch[sz]));
 21             val[sz++]=0;
 22         }
 23         u=ch[u][c];
 24     }
 25     val[u]=v;
 26 }
 27 int rak[maxn],hea[maxn],num;
 28 void cal(int u){
 29     if(val[u]){
 30         num++;
 31         rak[val[u]]=num;
 32         hea[num]=val[u];
 33         return ;
 34     }
 35     for(int i=0;i<26;i++){
 36         if(ch[u][i])
 37             cal(ch[u][i]);
 38     }
 39 }
 40 int sumv[maxn];
 41 int lowbit(int x){
 42     return x&(-x);
 43 }
 44 void add(int p,int v){
 45     for(int i=p;i<=n;i+=lowbit(i)){
 46         sumv[i]+=v;
 47     }
 48 }
 49 int query(int p){
 50     int res=0;
 51     for(int i=p;i>0;i-=lowbit(i)){
 52         res+=sumv[i];
 53     }
 54     return res;
 55 }
 56 int check(char *s){
 57     int u=0;int len=strlen(s);
 58     for(int i=0;i<len;i++){
 59         int c=s[i]-‘a‘;
 60         if(!ch[u][c])
 61             return 0;
 62         u=ch[u][c];
 63     }
 64     return val[u];
 65 }
 66 char s[maxn];
 67 int main(){
 68     scanf("%d%d",&n,&k);
 69     A[0]=1;A[1]=n-k+1;
 70     for(int i=2;i<=k;i++){
 71         A[i]=A[i-1]*(n+i-k)%mod;
 72     }
 73
 74     sz=1;
 75     for(int i=1;i<=n;i++){
 76         scanf("%s",s);
 77         insert(s,i);
 78     }
 79     num=0;
 80     cal(0);
 81     int u=0;
 82     scanf("%s",s);
 83     LL ans=0;
 84     int len=strlen(s);
 85     int num=0;
 86     for(int i=0;i<len;i++){
 87         int c=s[i]-‘a‘;
 88         u=ch[u][c];
 89         if(val[u]){
 90             int id=rak[val[u]];
 91            // printf("%d %d %d %d %lld\n",i,val[u],id,query(id-1),A(n-num-1,k-num-1));
 92             ans=(ans+(((id-1-query(id-1))%mod)*A[k-num-1])%mod)%mod;
 93            // printf("%lld\n",ans);
 94             add(id,1);
 95             u=0;
 96             num++;
 97         }
 98     }
 99     printf("%lld\n",ans+1);
100 return 0;
101 }

F-Probe Droids

不会做···

G-G. Rainbow Graph

题意

Roy和Biv有一个拥有n个结点的无向图,每条边有一个正整数权值和颜色。有三种颜色,红色,绿色,蓝色。可能有重边和自环。 Roy和Biv想要选出k条边,然后删除掉其他的边,且图还是联通的。然而,Roy看不见红色,Biv看不见蓝色,因此,他们必须选择边按照下面的规则:蓝色和绿色的边足够连接所有的点,红色和绿色的边足够连接所有的点。k条边满足条件的最小的。n,m<=100。

分析

个人感觉这个题炒鸡巧妙啊!!!

所以说连通的定义为:只用红色和绿色的边可以连通,且只用蓝色绿色的边也可以连通。Claris是用拟阵解释的,然鹅我不会,我只能用通俗点的方式来解释。定义条件一(M1)为只用红色绿色就能连通,条件二(M2)为只用蓝色绿色就能连通。建立有向图,原图每条边作为一个点,并添加源汇S和T。对于上一个k的一组最优解E中的某条边x,如果去掉它后仍然满足M1,则由S向x连边;若去掉它后仍然满足M2,则由x向T连边。对于E中某条边x和不在E中的某条边y,若将x换成y后满足M2,则由x向y连边;若满足M1,则由y向x连边。 用SPFA求出S到T的最短路,就能得到边数恰好减1的最优解。神奇吧??

下面说一下我的理解。如果去掉边i,条件一仍然满足,则S->i连边,若条件二仍然满足,则i->T连边。这个很好理解。如果i是集合内的边,j是集合外的边,如果交换i和j,条件2满足,则i向j连边。如果条件1满足,则j向i连边。 为什么要这样,因为现在是要找比原来集合少一条边的边集合,所以如果要替换,必须做到二换一。

时间复杂度是O(n^4)

H-Recovery

贪心的构造

I- Red Black Tree

题意

有一个n个节点的有根树,编号由1到n,有m个节点被涂成红色,剩下的涂成黑色。 你要选出一些节点集合来,使得集合内没有一个节点是另一个集合内节点的祖先节点。 另外,你要保证你的集合内恰好有k个红色的节点。有m个红色结点是红色的,对K=0,1,。。,m分别找出有多少符合条件的集合。

分析

比较裸的树形DP。设f[i][j]为以i为根结点的子树,选出j个红色结点的方案数。注意转移的时候。u结点有m个儿子结点,将其从左到右编号为1,2,3,...,m。设f[i][x]为1到i个结点1到i结点,选出有x个红色结点的方案数。f[i][x]=f[i-1][x-j]*f[i][j];

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <cstring>
 5 #include <vector>
 6
 7 using namespace std;
 8 typedef long long LL;
 9 const int maxn=200000+100;
10 const int mod=1e9+7;
11 const int maxm=1000+5;
12 vector<int>G[maxn];
13 int n,m;
14 int f[maxn][maxm],h[maxm],Size[maxn],red[maxn];
15 void dfs(int u){
16     f[u][0]=1;
17     for(int i=0;i<G[u].size();i++){
18         int v=G[u][i];
19         dfs(v);
20         for(int j=0;j<=Size[u]+Size[v]&&j<=m;j++)h[j]=0;
21         for(int j=0;j<=Size[u]&&j<=m;j++){
22             for(int k=0;k<=Size[v]&&j+k<=m;k++){
23                 h[j+k]=((LL)f[u][j]*f[v][k]+h[j+k])%mod;
24             }
25         }
26         for(int j=0;j<=Size[u]+Size[v]&&j<=m;j++)
27             f[u][j]=h[j];
28         Size[u]+=Size[v];
29     }
30     Size[u]+=red[u];
31     f[u][red[u]]=(f[u][red[u]]+1)%mod;
32 }
33 int main(){
34     while(scanf("%d%d",&n,&m)!=EOF){
35         memset(red,0,sizeof(red));
36         memset(f,0,sizeof(f));
37         for(int i=0;i<=n;i++)G[i].clear();
38
39         for(int i=2;i<=n;i++){
40             int a;
41             scanf("%d",&a);
42             G[a].push_back(i);
43         }
44         for(int i=1;i<=m;i++){
45             int a;
46             scanf("%d",&a);
47             red[a]=1;
48         }
49         dfs(1);
50         for(int i=0;i<=m;i++)
51             printf("%d\n",f[1][i]);
52     }
53 return 0;
54 }

J-Winter Festival

仍然不会做··我太菜了

K- Zoning Houses

题意

给出n个点的坐标和q个询问。每个询问给出一段区间[l,r],找出一个最小的正方形使得包含区间内所有的点。可以忽略区间内的一个点

分析

如果不考虑忽略一个点的话每次询问只要找出区间内点的最大最小横纵坐标就可以。忽略一个点一定优于或等于不忽略,所以直接考虑忽略哪个点。需要考虑的最多只有四个点,横坐标最大,横坐标最小,纵坐标最大,纵坐标最小。所以我需要查询出横坐标最大的最小的,次大的,次小的。 纵坐标同理。次大的  如果查询区间是[l,r]但是其中x是区间最大值,那么就再分别查询[l,x-1],[x+1,r]的区间最大值,来确定。

claris这个线段树真的是短小精悍,实在忍不住了,默默的贴在这

 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 typedef pair<int,int>P;
 5 const int N=100010,M=262150,inf=1000000010;
 6 int n,m,i,x,y,ans;
 7 P xmi[M],xma[M],ymi[M],yma[M];
 8 void build(int x,int a,int b){
 9     if(a==b){
10         scanf("%d%d",&xmi[x].first,&ymi[x].first);
11         xmi[x].second=ymi[x].second=a;
12         xma[x]=xmi[x];
13         yma[x]=ymi[x];
14         return;
15     }
16     int mid=(a+b)>>1;
17     build(x<<1,a,mid),build(x<<1|1,mid+1,b);
18     xmi[x]=min(xmi[x<<1],xmi[x<<1|1]);
19     xma[x]=max(xma[x<<1],xma[x<<1|1]);
20     ymi[x]=min(ymi[x<<1],ymi[x<<1|1]);
21     yma[x]=max(yma[x<<1],yma[x<<1|1]);
22 }
23
24 P askxmi(int x,int a,int b,int c,int d){
25     if(c>d)return P(inf,0);
26     if(c<=a&&b<=d)return xmi[x];
27     int mid=(a+b)>>1;
28     P t(inf,0);
29     if(c<=mid)t=askxmi(x<<1,a,mid,c,d);
30     if(d>mid)t=min(t,askxmi(x<<1|1,mid+1,b,c,d));
31     return t;
32 }
33 P askymi(int x,int a,int b,int c,int d){
34     if(c>d)return P(inf,0);
35     if(c<=a&&b<=d)return ymi[x];
36     int mid=(a+b)>>1;
37     P t(inf,0);
38     if(c<=mid)t=askymi(x<<1,a,mid,c,d);
39     if(d>mid)t=min(t,askymi(x<<1|1,mid+1,b,c,d));
40     return t;
41 }
42 P askxma(int x,int a,int b,int c,int d){
43     if(c>d)return P(-inf,0);
44     if(c<=a&&b<=d)return xma[x];
45     int mid=(a+b)>>1;
46     P t(-inf,0);
47     if(c<=mid)t=askxma(x<<1,a,mid,c,d);
48     if(d>mid)t=max(t,askxma(x<<1|1,mid+1,b,c,d));
49     return t;
50 }
51 P askyma(int x,int a,int b,int c,int d){
52     if(c>d)return P(-inf,0);
53     if(c<=a&&b<=d)return yma[x];
54     int mid=(a+b)>>1;
55     P t(-inf,0);
56     if(c<=mid)t=askyma(x<<1,a,mid,c,d);
57     if(d>mid)t=max(t,askyma(x<<1|1,mid+1,b,c,d));
58     return t;
59 }
60 inline int cal(int x,int y,int z){
61     return max(
62     max(askxma(1,1,n,x,z-1).first,askxma(1,1,n,z+1,y).first)-min(askxmi(1,1,n,x,z-1).first,askxmi(1,1,n,z+1,y).first)
63     ,
64     max(askyma(1,1,n,x,z-1).first,askyma(1,1,n,z+1,y).first)-min(askymi(1,1,n,x,z-1).first,askymi(1,1,n,z+1,y).first)
65     );
66 }
67 int main(){
68     scanf("%d%d",&n,&m);
69     build(1,1,n);
70     while(m--){
71         scanf("%d%d",&x,&y);
72         ans=cal(x,y,askxmi(1,1,n,x,y).second);
73         ans=min(ans,cal(x,y,askxma(1,1,n,x,y).second));
74         ans=min(ans,cal(x,y,askymi(1,1,n,x,y).second));
75         ans=min(ans,cal(x,y,askyma(1,1,n,x,y).second));
76         printf("%d\n",ans);
77     }
78 }

原文地址:https://www.cnblogs.com/LQLlulu/p/9513669.html

时间: 2024-07-30 21:44:16

North American Invitational Programming Contest 2018的相关文章

The North American Invitational Programming Contest 2017 题目

NAIPC 2017 Yin and Yang Stones 75.39% 1000ms 262144K A mysterious circular arrangement of black stones and white stones has appeared. Ming has been tasked with balancing the stones so that only one black and one white stone remain. Ming has two opera

ACM International Collegiate Programming Contest, Tishreen Collegiate Programming Contest (2018) Syria, Lattakia, Tishreen University, April, 30, 2018

ACM International Collegiate Programming Contest, Tishreen Collegiate Programming Contest (2018) Syria, Lattakia, Tishreen University, April, 30, 2018 Problem A. Can Shahhoud Solve it? Problem B. Defeat the Monsters Problem C. UCL Game Night Problem

ACM International Collegiate Programming Contest, JUST Collegiate Programming Contest (2018)

ACM International Collegiate Programming Contest, JUST Collegiate Programming Contest (2018) B. New Assignment 有n个人(1?≤?n?≤?104),有男有女,每个人都有一个id,现在这n个人分成学习互助小组,有三种组队模式,一个男人一组,一个女人一组,一男一女一组,如果要一男一女一组,那么这两人id的gcd要>1.保证任意三个人的gcd=1.求小组的组数最少是多少? 看起来是一个很裸的二

训练20191007 2017-2018 ACM-ICPC Latin American Regional Programming Contest

2017-2018 ACM-ICPC Latin American Regional Programming Contest 试题地址:http://codeforces.com/gym/101889 总体情况 总共通过7题CEFGHIJ.其中我完成HIJ三题.纯属被大佬带飞系列. 解题报告 H - Hard choice 签到题 #include <bits/stdc++.h> using namespace std; int a1,b1,c1,a2,b2,c2; int main() {

German Collegiate Programming Contest 2018?

B:Battle Royale Battle Royale games are the current trend in video games and Gamers Concealed Punching Circles (GCPC) is the most popular game of them all. The game takes place in an area that, for the sake of simplicity, can be thought of as a two-d

German Collegiate Programming Contest 2018? A. Attack on Alpha-Zet

题目链接https://nanti.jisuanke.com/t/28852 题目大意是 h*w 的平面,每两个点有且仅有一条路径,类似于封闭的联通空间,然后在这h*w个点中选取(标记为1~N)N个点(给了坐标),求从1号点按1~N的顺序走到N号点的路程. 练习赛的时候没有思路,队友说可以建树,但还是不清不楚没写出来. 做法是LCA. 将封闭的联通空间建树(点的位置与字符的位置有点麻烦),然后按顺序求两点的最近的公共祖先求深度得距离,最后得路程,算是一道LCA的模板. 1 #include <b

2017-2018 ACM-ICPC Latin American Regional Programming Contest Solution

A - Arranging tiles 留坑. B - Buggy ICPC 题意:给出一个字符串,然后有两条规则,如果打出一个辅音字母,直接接在原字符串后面,如果打出一个元音字母,那么接在原来的字符串后面之后再翻转整个字符串,在这两条规则之下,求有多少种打印给定字符串的方法 思路:如果第一个字符是辅音,那么答案为0 如果全是辅音或全是元音,那么答案为1 如果只有一个辅音,答案为len 否则是最中间两个元音中间的辅音字符个数+1 1 #include <bits/stdc++.h> 2 3 u

2017-2018 ACM-ICPC Latin American Regional Programming Contest GYM101889

挺有意思的一套题,题也没有啥毒瘤了,本来是队切的结果种种原因大家全挂机了. 只补了百人题,一共7个,其他的暂时先不补了,,也不会嘛qwq H:签到 1 #include <bits/stdc++.h> 2 using namespace std; 3 int a[18],b[18]; 4 int main(){ 5 cin>>a[1]>>a[2]>>a[3]>>b[1]>>b[2]>>b[3]; 6 int ans = 0

2017-2018 ACM-ICPC Latin American Regional Programming Contest

题面pdfhttps://codeforc.es/gym/101889/attachments/download/7471/statements-2017-latam-regional.pdf zyn感冒,两个人打.刚开始两题超迅速,40分钟后开始各种写不出,自闭.然后突然又开出两题. 4题全部1A,70名左右应该能稳个银. 说明卡题了可千万不能放弃!虽然可能简单题做不出来,过的多的题目做不出来,也不要放弃去开题. 以及周末这两场都说明一定要胆子大. B---Buggy ICPC[找规律] 题意