NOI2015

T1 4195: [Noi2015]程序自动分析

喵喵喵?这题普及组就能切了吧?直接离散后并查集合并相等关系,枚举每个不等关系判断即可.

 1 //Achen
 2 #include<algorithm>
 3 #include<iostream>
 4 #include<cstring>
 5 #include<cstdlib>
 6 #include<vector>
 7 #include<cstdio>
 8 #include<queue>
 9 #include<cmath>
10 #include<set>
11 #define For(i,a,b) for(int i=(a);i<=(b);i++)
12 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
13 const int N=1000007;
14 typedef long long LL; 
15 typedef double db;
16 using namespace std;
17 int T,n,fa[N],ls[N],sz;
18 
19 template<typename T> void read(T &x) {
20     char ch=getchar(); x=0; T f=1;
21     while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
22     if(ch=='-') f=-1,ch=getchar();
23     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
24 }
25 
26 struct node {
27     int i,j,e;
28     node(){}
29     node(int i,int j,int e):i(i),j(j),e(e){}
30 }p[N];
31 
32 int find(int x) { return x==fa[x]?x:fa[x]=find(fa[x]); }
33 int lik(int x,int y) {
34     if(find(x)!=find(y)) fa[find(x)]=find(y);
35 }
36 
37 int main() {
38 #ifdef DEBUG
39     freopen(".in","r",stdin);
40     freopen(".out","w",stdout);
41 #endif
42     read(T);
43     while(T--) {
44         read(n); sz=0;
45         For(t,1,n) { 
46             int i,j,e;
47             read(i); read(j); read(e);
48             ls[++sz]=i; ls[++sz]=j;
49             p[t]=node(i,j,e);
50         }
51         sort(ls+1,ls+sz+1);
52         int tpsz=unique(ls+1,ls+sz+1)-(ls+1);
53         sz=tpsz;
54         For(i,1,sz) fa[i]=i;
55         For(i,1,n) {
56             p[i].i=lower_bound(ls+1,ls+sz+1,p[i].i)-ls;
57             p[i].j=lower_bound(ls+1,ls+sz+1,p[i].j)-ls;
58             if(p[i].e) lik(p[i].i,p[i].j);
59         }
60         int fl=1;
61         For(i,1,n) if(!p[i].e) {
62             int x=p[i].i,y=p[i].j;
63             if(find(x)==find(y)) {
64                 fl=0;
65                 break;
66             }
67         }
68         if(!fl) puts("NO");
69         else puts("YES");
70     }
71     return 0;
72 }
73 /*
74 2
75 2
76 1 2 1
77 1 2 0
78 2
79 1 2 1
80 2 1 1
81 */
View Code

 

T2 4196: [Noi2015]软件包管理器

??? 裸的树剖,不知道出题人怎么想的.

  1 //Achen
  2 #include<algorithm>
  3 #include<iostream>
  4 #include<cstring>
  5 #include<cstdlib>
  6 #include<vector>
  7 #include<cstdio>
  8 #include<queue>
  9 #include<cmath>
 10 #include<set>
 11 #define For(i,a,b) for(int i=(a);i<=(b);i++)
 12 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
 13 const int N=100007;
 14 typedef long long LL; 
 15 typedef double db;
 16 using namespace std;
 17 int n,q;
 18 char o[20];
 19 
 20 template<typename T> void read(T &x) {
 21     char ch=getchar(); x=0; T f=1;
 22     while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
 23     if(ch=='-') f=-1,ch=getchar();
 24     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
 25 }
 26 
 27 int sg[N<<2],lz[N<<2];
 28 #define lc x<<1
 29 #define rc ((x<<1)|1)
 30 #define mid ((l+r)>>1)
 31 void add_it(int x,int len,int v) {
 32     if(v==1) sg[x]=len; else sg[x]=0; lz[x]=v; 
 33 }
 34 
 35 void down(int x,int l_len,int r_len) {
 36     if(!lz[x]) return;
 37     if(l_len) add_it(lc,l_len,lz[x]);
 38     if(r_len) add_it(rc,r_len,lz[x]);
 39     lz[x]=0;
 40 }
 41 
 42 void update(int x,int l,int r,int ql,int qr,int v) {
 43     if(l>=ql&&r<=qr) {
 44         add_it(x,r-l+1,v); return;
 45     }
 46     down(x,mid-l+1,r-mid);
 47     if(ql<=mid) update(lc,l,mid,ql,qr,v);
 48     if(qr>mid) update(rc,mid+1,r,ql,qr,v);
 49     sg[x]=sg[lc]+sg[rc];
 50 }
 51 
 52 int qry(int x,int l,int r,int ql,int qr) {
 53     if(l>=ql&&r<=qr) return sg[x];
 54     down(x,mid-l+1,r-mid);
 55     if(qr<=mid) return qry(lc,l,mid,ql,qr);
 56     if(ql>mid) return qry(rc,mid+1,r,ql,qr);
 57     return qry(lc,l,mid,ql,qr)+qry(rc,mid+1,r,ql,qr);
 58 }
 59 
 60 int ecnt,fir[N],nxt[N],to[N];
 61 void add(int u,int v) {
 62     nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v;
 63 }
 64 
 65 int sz[N],R[N],f[N];
 66 void dfs(int x,int fa) {
 67     f[x]=fa; sz[x]=1; R[x]=R[fa]+1;
 68     for(int i=fir[x];i;i=nxt[i]) { 
 69         dfs(to[i],x);
 70         sz[x]+=sz[to[i]];
 71     }
 72 }
 73 
 74 int top[N],dfn[N],low[N],tid[N],dfs_clock;
 75 void DFS(int x,int Top) {
 76     top[x]=Top;
 77     dfn[x]=++dfs_clock;
 78     tid[dfn[x]]=x;
 79     int mxson=0;
 80     for(int i=fir[x];i;i=nxt[i]) if(!mxson||sz[mxson]<sz[to[i]]) mxson=to[i];
 81     if(mxson) DFS(mxson,Top);
 82     for(int i=fir[x];i;i=nxt[i]) if(to[i]!=mxson) DFS(to[i],to[i]);
 83     low[x]=dfs_clock;
 84 }
 85 
 86 int schange(int x,int y,int v) {
 87     while(top[x]!=top[y]) {
 88         if(R[top[x]]<R[top[y]]) swap(x,y);
 89         update(1,1,n,dfn[top[x]],dfn[x],v);
 90         x=f[top[x]];
 91     }
 92     if(dfn[x]>dfn[y]) swap(x,y);
 93     update(1,1,n,dfn[x],dfn[y],v);
 94 }
 95 
 96 int sqry(int x,int y) {
 97     int rs=0;
 98     while(top[x]!=top[y]) {
 99         if(R[top[x]]<R[top[y]]) swap(x,y);
100         rs+=qry(1,1,n,dfn[top[x]],dfn[x]);
101         x=f[top[x]];
102     }
103     if(dfn[x]>dfn[y]) swap(x,y);
104     rs+=qry(1,1,n,dfn[x],dfn[y]);
105     return rs;
106 }
107 
108 int main() {
109 #ifdef DEBUG
110     freopen(".in","r",stdin);
111     freopen(".out","w",stdout);
112 #endif
113     read(n);
114     For(i,2,n) {
115         int fa; read(fa); 
116         fa++; add(fa,i);
117     }
118     dfs(1,0);
119     DFS(1,1);
120     update(1,1,n,1,n,1);
121     read(q);
122     For(ti,1,q) {
123         int x;
124         scanf("%s",o);
125         read(x); x++;
126         if(o[0]=='i') {
127             printf("%d\n",sqry(1,x));
128             schange(1,x,-1);
129         }
130         else {
131             printf("%d\n",sz[x]-qry(1,1,n,dfn[x],low[x]));
132             update(1,1,n,dfn[x],low[x],1);
133         }
134     }
135     return 0;
136 }
View Code

 

T3 4197: [Noi2015]寿司晚宴

容易想到状压dp,小于sqrtn的素因子只有8个,每个数大于sqrtn的素因子仅1个,按这个素因子把数分成不相干的若干类.每一类只能一个人选.

然后就不知道怎么做了.

可能从30分暴力开始想容易想到一点.

30分数据n<=30,那么状压所有素因子,

f[i][j]表示第1个人选了i这些因子,第2个人选了j这些因子的方案数.

n<=500时

对于仅含有小于sqrtn的素因子的数可以和30分一样状压dp.

对于含有大于sqrtn的素因子的数,相互直接互不影响,那么分成若干组分别dp就好了.

每一组的dp中,g[0/1][i][j]表示这一组由第0/1个人选的方案数.

每一组的初值g[0][i][j]=g[1][i][j]=f[i][j]

最后答案f[i][j]=g[0][i][j]+g[1][i][j]-f[i][j](减去这一组两个人都啥都没选)

 1 //Achen
 2 #include<algorithm>
 3 #include<iostream>
 4 #include<cstring>
 5 #include<cstdlib>
 6 #include<vector>
 7 #include<cstdio>
 8 #include<queue>
 9 #include<cmath>
10 #include<set>
11 #define For(i,a,b) for(int i=(a);i<=(b);i++)
12 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
13 const int N=259;
14 typedef long long LL; 
15 typedef double db;
16 using namespace std;
17 int n,mod,p[150],sz,ok[507],allin[507];
18 LL f[N][N],g[2][N][N],ans;
19 
20 template<typename T> void read(T &x) {
21     char ch=getchar(); x=0; T f=1;
22     while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
23     if(ch=='-') f=-1,ch=getchar();
24     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
25 }
26 
27 int main() {
28 #ifdef DEBUG
29     freopen(".in","r",stdin);
30     freopen(".out","w",stdout);
31 #endif
32     read(n); read(mod);
33     For(i,2,n) {
34         int fl=1;
35         For(j,2,i-1) if(i%j==0) {
36             fl=0; break;
37         }
38         if(fl) {
39             p[++p[0]]=i;
40             if(i*i<=n) sz++;
41         }
42     }
43     For(i,2,n) {
44         int tp=i;
45         For(j,1,sz) if(tp%p[j]==0) {
46             ok[i]|=(1<<j-1);
47             while(tp%p[j]==0) tp/=p[j];
48         }
49         if(tp==1) allin[i]=1;
50     }
51     f[0][0]=1;
52     int nn=(1<<sz)-1;
53     For(x,2,n) if(allin[x]) {
54         Rep(i,nn,0) Rep(j,nn,0) if(f[i][j]) {
55             if(!(i&ok[x])) (f[i][j|ok[x]]+=f[i][j])%=mod;
56             if(!(j&ok[x])) (f[i|ok[x]][j]+=f[i][j])%=mod;
57         }
58     }
59     For(id,sz+1,p[0]) {
60         For(i,0,nn) For(j,0,nn) g[0][i][j]=g[1][i][j]=f[i][j];
61         for(int x=p[id];x<=n;x+=p[id]) 
62             Rep(i,nn,0) Rep(j,nn,0) {
63                 if(!(i&ok[x])) (g[1][i][j|ok[x]]+=g[1][i][j])%=mod;
64                 if(!(j&ok[x])) (g[0][i|ok[x]][j]+=g[0][i][j])%=mod;
65             }
66         For(i,0,nn) For(j,0,nn) f[i][j]=(g[0][i][j]+g[1][i][j]-f[i][j]+mod)%mod;
67     }
68     For(i,0,nn) For(j,0,nn) (ans+=f[i][j])%=mod;
69     printf("%lld\n",ans);
70     return 0;
71 }
View Code

 

T4 4198: [Noi2015]荷马史诗

感觉是树上贪心乱搞.

然后得知有一种叫哈夫曼树的奥妙的玩意.

哈夫曼树:

一些叶子有权值,一颗树的权证为所有叶子的权值乘以叶子的深度的和,求权值最小的树.一般是二叉的.

先把所有叶子看成一颗单独的树,每次取出权值最小的两个叶子合并,合并后的权值为两个叶子的权值和.

到这道题上,就是求一个k叉的哈夫曼树.那么每次取出权值最小的k个树来合并.

当(n-1)%(k-1)不等于0时,需补上一些权值为0的叶子再做.

要使得深度最大的叶子最小,每次合并时存在权值相同的树时,规定深度小的树权值为小即可.

 1 //Achen
 2 #include<algorithm>
 3 #include<iostream>
 4 #include<cstring>
 5 #include<cstdlib>
 6 #include<vector>
 7 #include<cstdio>
 8 #include<queue>
 9 #include<cmath>
10 #include<set>
11 #define For(i,a,b) for(int i=(a);i<=(b);i++)
12 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
13 const int N=200007;
14 typedef long long LL; 
15 typedef double db;
16 using namespace std;
17 LL n,k,w[N],anstot,ansh;
18 
19 template<typename T> void read(T &x) {
20     char ch=getchar(); x=0; T f=1;
21     while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
22     if(ch=='-') f=-1,ch=getchar();
23     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
24 }
25 
26 #define pr pair<LL,LL>
27 #define fi first
28 #define se second
29 pr p[N];
30 priority_queue<pr,vector<pr>,greater<pr> >que;
31 void build(int n) {
32     For(i,1,n) que.push(p[i]);
33     for(;;) {
34         pr y; 
35         LL W=0,H=0;
36         For(i,1,k) {
37             pr x=que.top();
38             W+=x.fi;
39             H=max(H,x.se+1);
40             que.pop();
41         }
42         y.fi=W; y.se=H;
43         anstot+=W;
44         if(que.empty()) {
45             ansh=y.se;
46             break;
47         }
48         que.push(y);
49     }
50 }
51 
52 int main() {
53 #ifdef DEBUG
54     freopen(".in","r",stdin);
55     freopen(".out","w",stdout);
56 #endif
57     read(n); read(k);
58     For(i,1,n) read(w[i]);
59     while((n-1)%(k-1)) n++;
60     For(i,1,n) { p[i].fi=w[i]; p[i].se=0; }
61     build(n);
62     printf("%lld %lld\n",anstot,ansh);
63     return 0;
64 }
View Code

 

T5品酒大会

传送门

 

posted @ 2018-04-12 09:16  啊宸  阅读(341)  评论(0编辑  收藏  举报