是时候开刷NOI了

整天挨着毛爷爷,压力好大。。

看毛爷爷即将炖完NOI,我的确也该刷了

原则是从头到尾自己想(虽然看了一次题解),可以不A掉。

NOI2009

day1:

T1

题目略神,我还是不讲了。。。(就这题我WA了好多遍 TAT)

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <bitset>
 5 #include <vector>
 6  
 7 #define N 20010
 8  
 9 using namespace std;
10  
11 struct edge{
12     int x,to;
13 }E[N<<2];
14  
15 int n,a[N],pre[N],totE,g[N];
16 bitset<N> v;
17 vector<int> G[N];
18  
19 #define p G[x][i]
20  
21 void ade(int x,int y){
22     G[x].push_back(y);
23 }
24  
25 int find(int x){
26     v[x]=1;
27     int len=G[x].size();
28     for(int i=0;i<len;i++)
29         if(!v[p]){
30             v[p]=1;
31             if(!pre[p]||find(pre[p])){
32                 pre[p]=x; pre[x]=p;
33                 return 1;
34             }
35         }
36     return 0;
37 }
38  
39 int main(){
40     freopen("transform.in","r",stdin);
41     freopen("transform.out","w",stdout);
42     scanf("%d",&n);
43     for(int i=1;i<=n;i++){
44         scanf("%d",&a[i]);
45     }
46     for(int i=1;i<=n;i++){
47         if(i-a[i]>=1) G[i].push_back(n+i-a[i]);
48         else G[i].push_back(n+i-a[i]+n);
49         if(i+a[i]<=n) G[i].push_back(n+i+a[i]);
50         else G[i].push_back(i+a[i]);
51     }
52     for(int i=1;i<=n;i++) sort(G[i].begin(),G[i].end());
53     int ans=0;
54     for(int i=n;i>=1;i--){
55         v.reset();
56         if(find(i)) ans++;
57     }
58     if(ans!=n){
59         puts("No Answer");
60     }
61     else{
62         for(int i=1;i<n;i++) printf("%d ",pre[i]-n-1);
63         printf("%d
",pre[n]-n-1);
64     }
65     return 0;
66 }
View Code

T2

脑补一下,这个应该是一个单峰函数,果断三分。

爆long long QAQ,这要是NOI我就被坑死啦,long double过。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4  
 5 #define LL long long
 6 #define N 200010
 7 #define LD long double
 8  
 9 using namespace std;
10  
11 int n,P;
12 int len[N],pre[N];
13 LL L;
14 LD f[N];
15 char S[N][52];
16  
17 LD qpow(LD x,LL n){
18     LD ans=1;
19     for(;n;n>>=1,x*=x)
20         if(n&1) ans*=x;
21     return ans;
22 }
23  
24 LD Abs(LL x){
25     if(x<0) return -(LD)x;
26     return (LD)x;
27 }
28  
29 LD F(int i,int j){
30     return f[j]+
31         qpow(Abs(L-(len[i]-len[j]+i-j-1LL)),P); 
32 }
33  
34 int find(int i){
35     int l=0,r=i-1,m1,m2;
36     while(r-l>10){
37         m1=l+(r-l)/3;
38         m2=r-(r-l)/3;
39         if(F(i,m1)<F(i,m2)) r=m2;
40         else l=m1;
41     }
42     LD ans=F(i,0);
43     int pos=0;
44     for(int t=l;t<=r;t++)
45         if(F(i,t)<ans){
46             ans=F(i,t);
47             pos=t;
48         }
49     return pos;
50 }
51  
52 void print(int t){
53     if(pre[t]) print(pre[t]);
54     for(int i=pre[t]+1;i<t;i++){
55         printf("%s ",S[i]);
56     }
57     printf("%s
",S[t]);
58 }
59  
60 int main(){
61     freopen("noi09_poet.in","r",stdin);
62     freopen("noi09_poet.out","w",stdout);
63     int T;
64     scanf("%d",&T);
65     while(T--){
66         scanf("%d %lld %d",&n,&L,&P);
67         for(int i=1;i<=n;i++){
68             scanf("%s",S[i]);
69             len[i]=strlen(S[i]);
70         }
71         for(int i=2;i<=n;i++) len[i]+=len[i-1];
72         memset(f,127,sizeof(f));
73         f[0]=0;
74         for(int i=1;i<=n;i++){
75             int j=find(i);
76             f[i]=f[j]+qpow(Abs(L-(len[i]-len[j]+i-j-1LL)),P);
77             pre[i]=j;
78         }
79         if(f[n]>1e18){
80             puts("Too hard to arrange");
81         }
82         else{
83             printf("%lld
",(LL)(f[n]));
84             print(n);
85         }
86         puts("--------------------");
87     }
88     return 0;
89 }
View Code

T3

QAQ好难,膜毛爷爷。

首先所谓 (频度 x 深度) 我们可以每过一层就加上当前的频度得到答案。

利用先序遍历的特殊性质(TAT 其实想到这个就差不多了),考虑dp。

f[i][j][k] 表示先序遍历从 i 到 j 作为一个子树(可能多个),而且满足所有权值小于等于k的最小花费。

转移分两种情况,修改当前root权值,修改子树权值。

$O(n^4)$ dp即可。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <iostream>
 5  
 6 #define N 80
 7 #define LL long long
 8 #define INF 0x7f7f7f7f7f7f7f7fLL
 9 #define debug(x) cout<<#x<<" = "<<x<<endl;
10  
11 using namespace std;
12  
13 int n,tot0;
14 int a[N],b[N],c[N],X[N];
15 LL K;
16 LL dp[N][N][N];
17 LL s[N][N];
18  
19 /*
20 O(n^5)
21  
22 f[i][j][k]
23 i到j之间的所有数值大于k,
24 消灭当前点    f[i][j][k] = min{ f[i][p-1][k] + f[p+1][j][k] + s[i][j] + K }
25 不消灭当前点    f[i][j][k] = min{ f[i][p-1][b[p]] + f[p+1][j][b[p]] + s[i][j] }
26 */
27  
28 LL F(int i,int j,int k){
29     if(i>j) return 0;
30 //    printf("%d %d %d
",i,j,k);
31     if(dp[i][j][k]) return dp[i][j][k];
32     if(i==j) return dp[i][j][k]=b[i]<k ?K+c[i]:c[i];
33     dp[i][j][k]=INF;
34     for(int p=i;p<=j;p++){    //改当前点权 
35         dp[i][j][k]=min(dp[i][j][k],F(i,p-1,k) + F(p+1,j,k) + s[i][j] + K);
36         if(b[p]>=k){    //不改当前点权
37             dp[i][j][k]=min(dp[i][j][k],F(i,p-1,b[p]) + F(p+1,j,b[p]) + s[i][j]);
38         }
39     }
40     return dp[i][j][k];
41 }
42  
43 void init(){
44     for(int i=1;i<n;i++)
45         for(int j=i+1;j<=n;j++)
46             if(a[i]>a[j]){
47                 swap(a[i],a[j]);
48                 swap(b[i],b[j]);
49                 swap(c[i],c[j]);
50             }
51     sort(X+1,X+n+1);
52     tot0=1;
53     for(int i=2;i<=n;i++)
54         if(X[i]!=X[i-1]) X[++tot0]=X[i];
55     for(int i=1;i<=n;i++)
56         b[i]=lower_bound(X+1,X+tot0+1,b[i])-X;
57     for(int i=1;i<=n;i++){
58         s[i][i]=c[i];
59         for(int j=i+1;j<=n;j++)
60             s[i][j]=s[i][j-1]+c[j];
61     }
62 }
63  
64 int main(){
65     freopen("treapmod.in","r",stdin);
66     freopen("treapmod.out","w",stdout);
67     scanf("%d%d",&n,&K);
68     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
69     for(int i=1;i<=n;i++){
70         scanf("%d",&b[i]);
71         X[i]=b[i];
72     }
73     for(int i=1;i<=n;i++) scanf("%d",&c[i]);
74     init();
75     LL ans=INF;
76     for(int i=1;i<=n;i++){
77         ans=min(ans,F(1,n,b[i]));
78     }
79     cout<<ans<<endl;
80     return 0;
81 }
View Code

day2

T1:

裸网络流,注意要拓扑一下,还要判环,环内的植物不能碰。

T2:

又是一道$dp$,思路很神(TAT 实在不会,看了题解)。

就是将 平方和 转化为结果相同的方案对数(自己也算)

然后裸dp上。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4  
 5 #define N 510
 6 #define mod 1024523
 7  
 8 using namespace std;
 9  
10 /*
11 f[i][j][k]表示上面取了上i下j,上k。 
12 */
13  
14 char S1[N],S2[N];
15 int f[N][N][N],n,m;
16  
17 int add(int a,int b){
18     if(a+b<mod) return a+b;
19     return a+b-mod;
20 }
21  
22 int main(){
23     freopen("ballb.in","r",stdin);
24     freopen("ballb.out","w",stdout);
25     scanf("%d%d%s%s",&n,&m,S1,S2);
26     reverse(S1,S1+n);
27     reverse(S2,S2+m);
28     f[0][0][0]=1;
29     for(int i=0;i<=n;i++){
30         for(int j=0;j<=m;j++){
31             for(int k=0;k<=n;k++){
32                 if(!f[i][j][k]) continue;
33                 int l = i+j-k;
34                 if(l<0) break;
35                 //printf("f[%d][%d][%d] = %d
",i,j,k,f[i][j][k]);
36                 if(i<n && k<n && S1[i]==S1[k]){
37                     f[i+1][j][k+1] = add(f[i+1][j][k+1],f[i][j][k]);
38                 }
39                 if(i<n && l<m && S1[i]==S2[l]){
40                     f[i+1][j][k] = add(f[i+1][j][k],f[i][j][k]);
41                 }
42                 if(j<m && k<n && S2[j]==S1[k]){
43                     f[i][j+1][k+1] = add(f[i][j+1][k+1],f[i][j][k]); 
44                 }
45                 if(j<m && l<m && S2[j]==S2[l]){
46                     f[i][j+1][k] = add(f[i][j+1][k],f[i][j][k]);
47                 }
48             }
49         }
50     }
51     printf("%d
",f[n][m][n]);
52     return 0;
53 }
View Code

T3:

很好的提交答案题。

做好了70分吧。

NOI 2008

TAT QAQ QWQ TWT

题出这么难也是醉了。

day1:

T1

找环然后分类讨论,情况不多就三种。

可是好多细节呀,蒟蒻我是调不出来的。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4  
 5 using namespace std;
 6  
 7 template<typename T> T abs(T x){
 8     if(x>0) return x;
 9     return -x;
10 }
11 template<typename T> T gcd(T x, T y){
12     for(T t;x!=0;t=x,x=y%x,y=t);
13     return y;
14 }
15  
16 const int Maxn =2000010;
17 const int Maxm =2000010;
18  
19 struct edge{
20     int to,x,v;
21 }Edges[Maxm];
22  
23 int totE=0,head[Maxn];
24  
25 void addedge(int u,int v,int w){
26     Edges[++totE]=(edge){head[u],v,w};
27     head[u]=totE;
28 }
29  
30 int n,m,ans=0,d[Maxn],maxt,mint;
31 bool vis[Maxn];
32  
33 void dfs(int x){
34     vis[x]=1;
35     for(int i=head[x];i;i=Edges[i].to){
36         int p=Edges[i].x;
37         if(vis[p]) ans=gcd(ans,abs(d[x]+Edges[i].v-d[p]));
38         else d[p]=d[x]+Edges[i].v,dfs(p);
39     }
40 }
41  
42 void find(int x){
43     vis[x]=1;
44     maxt=max(maxt,d[x]);
45     mint=min(mint,d[x]);
46     for(int i=head[x];i;i=Edges[i].to){
47         int p=Edges[i].x;
48         if(!vis[p]) d[p]=d[x]+Edges[i].v,find(p);
49     }
50 }
51  
52 int main(){
53     freopen("party2008.in","r",stdin);
54     freopen("party2008.out","w",stdout);
55     scanf("%d%d",&n,&m);
56     int u,v,tmp;
57     for(int i=1;i<=m;i++){
58         scanf("%d%d",&u,&v);
59         addedge(u,v,1);
60         addedge(v,u,-1);
61     }
62     for(int i=1;i<=n;i++)
63         if(!vis[i]) d[i]=0,dfs(i);
64     if(ans){
65         for(tmp=3;tmp<ans&&ans%tmp;tmp++);
66         //cout<<"case 1
";
67     }
68     else{
69         memset(vis,0,sizeof(vis));
70         tmp=3;
71         for(int i=1;i<=n;i++)
72             if(!vis[i]){
73                 maxt=mint=d[i]=0;
74                 find(i);
75                 ans+=maxt-mint+1;
76             }
77     }
78     if(ans<3) ans=tmp=-1;
79     printf("%d %d
",ans,tmp);
80     return 0;
81 }
View Code

T2

相对温暖的一道题。

可以发现一个条件:答案是 $O(logn)$ 级的(为啥我也不知道)。

然后变成了经典问题,直接枚举【不便利值】树形dp方案数,$f[i][j]$表示 $i$ 这个点向下连 $j$ 条边的方案数,直到方案数不为0为止。

注意0和mod后为0不同,因为要判断是否有方案,所以如果是因为mod而变成的0记做mod。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <vector>
 5 #include <queue>
 6  
 7 #define Maxn 100010
 8 typedef long long LL;
 9  
10 using namespace std;
11  
12 int n,m,Q,dep[Maxn];
13 LL f[Maxn][21][3];
14 vector<int> G[Maxn];
15  
16 /*
17 link = f[p][j][0] + f[p][j][1]
18 not_link = f[p][j-1][0] + f[p][j-1][1] + f[p][j-1][2]
19  
20 f[i][j][2] = f[i][j][2] * not_link + f[i][j][2]
21 f[i][j][1] = f[i][j][1] * not_link + f[i][j][0] * link
22 f[i][j][0] = f[i][j][0] * not_link
23 */
24  
25 bool find_circle(int x,int tp){
26     for(int i=0;i<G[x].size();i++){
27         if(G[x][i]==tp) continue;
28         if(dep[G[x][i]]) return 1;
29         dep[G[x][i]]=dep[x]+1;
30         if(find_circle(G[x][i],x)) return 1;
31     }
32     return 0;
33 }
34  
35 bool not_a_tree(int x){
36     dep[x]=1;
37     if(find_circle(x,0)) return 1;
38     for(int i=1;i<=n;i++)
39         if(!dep[i]) return 1;
40     return 0;
41 }
42  
43 LL Mod(LL x){
44     if(x==0) return 0;
45     if(x%Q==0) return Q;
46     return x%Q;
47 }
48  
49 LL dp(int x,int tp,int j){
50     f[x][j][1]=f[x][j][2]=0LL;
51     f[x][j][0]=1LL;
52     for(int i=0;i<G[x].size();i++){
53         int p=G[x][i];
54         if(p==tp) continue;
55         dp(p,x,j);
56         int not_link=0,link=0;
57         link =Mod(f[p][j][0]+f[p][j][1]);
58         if(j>0) not_link =Mod(f[p][j-1][0]+Mod(f[p][j-1][1]+f[p][j-1][2]));
59         f[x][j][2] =Mod(f[x][j][2]*not_link)+Mod(f[x][j][1]*link);
60         f[x][j][2] =Mod(f[x][j][2]);
61         f[x][j][1] =Mod(f[x][j][1]*not_link)+Mod(f[x][j][0]*link);
62         f[x][j][1] =Mod(f[x][j][1]);
63         f[x][j][0] =Mod(f[x][j][0]*not_link);
64     }
65     return Mod(f[x][j][0]+Mod(f[x][j][1]+f[x][j][2]));
66 }
67  
68 int main(){
69     freopen("design.in","r",stdin);
70     freopen("design.out","w",stdout);
71     scanf("%d%d%d",&n,&m,&Q);
72     int u,v,tmp=0;
73     LL ans=0;
74     for(int i=1;i<=m;i++){
75         scanf("%d%d",&u,&v);
76         G[u].push_back(v);
77         G[v].push_back(u);
78     }
79     if(n!=m+1||not_a_tree(1)){
80         puts("-1
-1");
81         return 0;
82     }
83     while(ans<=0) ans=dp(1,0,tmp++);
84     printf("%d
%lld
",tmp-1,ans==Q? 0:ans);
85     return 0;
86 }
View Code

T3

蒟蒻表示自己图论超级渣。

以前看题解过了,现在还不懂。

day2

T1

妈呀,基环外向树上dp,醉了,还是概率dp。

用贪心水到了40分,好像有人说可以70分,咦是我交的题库上的数据太强了吗。

T2

day2的温暖题。

QAQ 但是好寒冷。

直接转化一下,二维树状数组。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4  
 5 #define Maxn 1010
 6 #define Maxc 1000010
 7  
 8 typedef int Se[Maxn*3][Maxn<<2];
 9  
10 using namespace std;
11  
12 int n,T,len,m;
13 Se a,b;
14 struct Cloud{
15     int t,p;
16 }clou[Maxc];
17  
18 void Add(Se a,int x,int y,int d){
19     for(int i=x+1;i<len*3+2;i+=i&-i)
20         for(int j=y+1;j<(len<<2)+1;j+=j&-j)
21             a[i][j]+=d;
22 }
23  
24 int Ask(Se a,int x,int y){
25     int ans=0;
26     for(int i=x+1;i;i-=i&-i)
27         for(int j=y+1;j;j-=j&-j)
28             ans+=a[i][j];
29     return ans;
30 }
31  
32 void Add1(int x,int y,int d){
33     Add(a,x,x+y,d);
34 }
35  
36 void Add2(int x,int y,int d){
37     Add(b,x-len,y-x+m,d);
38 }
39  
40 void update(int c,int d){
41     int t=clou[c].t,p=clou[c].p;
42     Add1(t,p,d);
43     if(t<=len) Add1(t+n,p,d);
44     Add2(t+n,p,d);
45     if(t>=len) Add2(t,p,d);
46 }
47  
48 int Ask1(int x0,int y0,int x1,int y1){
49     return Ask(a,x1,x1+y1) - Ask(a,x0-1,x1+y1)
50     - Ask(a,x1,x0+y0-1) + Ask(a,x0-1,x0+y0-1);
51 }
52  
53 int Ask2(int x0,int y0,int x1,int y1){
54     return Ask(b,x1-len,y1-x1+m) - Ask(b,x0-len-1,y1-x1+m)
55         - Ask(b,x1-len,y0-x0+m-1) + Ask(b,x0-len-1,y0-x0+m-1);
56 }
57  
58 int query(int t,int L,int R){
59     int ans=Ask1(t,L,t+R,len),d=len==R;
60     if(!R) return ans;
61     return ans+=Ask2(t+n-R+d,L-R+d,t+n-1,len+R-1);
62 }
63  
64 int main(){
65     freopen("noi2008_candy.in","r",stdin);
66     freopen("noi2008_candy.out","w",stdout);
67     scanf("%d%d",&T,&len);
68     n=2*len; m=2*n;
69     for(int i=1;i<=T;i++){
70         int K,t,c,L,R,d;
71         scanf("%d%d",&K,&t);
72         t%=n;
73         if(K==1){
74             scanf("%d%d%d%d",&c,&L,&R,&d);
75             clou[c].t=(t-d*L+n)%n;
76             clou[c].p=R-L;
77             update(c,1);
78         }
79         else if(K==2){
80             scanf("%d%d",&L,&R);
81             printf("%d
",query(t,L,R));
82         }
83         else{
84             scanf("%d",&c);
85             update(c,-1);
86         }
87     }
88     return 0;
89 }
View Code

T3

提交答案题,还没做

继续

NOI2010

Day1

T1:能量采集:SB题,随便搞

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4  
 5 #define LL long long
 6 #define Maxn 100010
 7  
 8 using namespace std;
 9  
10 LL n,m,ans;
11 LL phi[Maxn]={0,1,0};
12  
13 int main(){
14     freopen("energy2010.in","r",stdin);
15     freopen("energy2010.out","w",stdout);
16     scanf("%lld%lld",&n,&m);
17     if(n<m) swap(n,m);
18     for(int i=2;i<=m;i++){
19         if(phi[i]) continue;
20         for(int j=i;j<=m;j+=i){
21             if(!phi[j]) phi[j]=j;
22             phi[j]=phi[j]*(i-1)/i;
23         }
24     }
25     for(int i=1;i<=m;i++){
26         ans+=(n/i)*(m/i)*phi[i];
27     }
28     ans=(ans-m*n)*2+m*n;
29      printf("%lld
",ans);
30     return 0;
31 }
View Code

T2:超级钢琴。

区间裂解,就是找到前K大的子区间和

ST+堆,随便搞。

#include <cstdio>
#include <queue>
using namespace std;
 
typedef long long LL;
 
const int maxn = 500010;
 
struct Node {
    LL x; int l, r, i;
    bool operator < (const Node &A) const {
        return x < A.x;
    }
};
priority_queue<Node> pq;
 
int n, K, L, R;
LL S[maxn];
int rmq[20][maxn];
 
void RMQ_init() {
    int k = 0; for (; (1 << k+1) < n+1; ++ k);
    for (int i = 0; i <= n; ++ i) rmq[0][i] = i;
    
    for (int j = 1; j <= k; ++ j)
        for (int i = 0; i+(1<<j)-1 <= n; ++ i) {
            int p = rmq[j-1][i], q = rmq[j-1][i+(1<<j-1)];
            rmq[j][i] = S[p] < S[q] ? p : q;
        }
}
int RMQ(int l, int r) {
    int z = r-l+1;
    int k = 0; for (; (1 << k+1) < z; ++ k);
    int p = rmq[k][l], q = rmq[k][r-(1<<k)+1];
    return S[p] < S[q] ? p : q;
}
 
int main() {
    freopen("piano.in", "r", stdin);
    freopen("piano.out", "w", stdout);
    
    scanf("%d%d%d%d", &n, &K, &L, &R);
    
    for (int i = 1; i <= n; ++ i) {
        int x; scanf("%d", &x);
        S[i] = S[i-1] + x;
    }
    RMQ_init();
    
    for (int i = 1; i <= n; ++ i) {
        int a = i-R, b = i-L; if (a < 0) a = 0;
        if (b >= 0) pq.push((Node){S[i] - S[RMQ(a, b)], a, b, i});
    }
    
    LL res = 0;
    while (K --) {
        if (pq.empty()) break;
        Node x = pq.top(); pq.pop();
        res += x.x; int t = RMQ(x.l, x.r);
        if (x.l <= t-1) pq.push((Node){S[x.i] - S[RMQ(x.l, t-1)], x.l, t-1, x.i});
        if (t+1 <= x.r) pq.push((Node){S[x.i] - S[RMQ(t+1, x.r)], t+1, x.r, x.i});
    }
    printf("%lld
", res);
    
    fclose(stdin); fclose(stdout);
    return 0;
}
View Code

T3:海拔

不想写对偶图,懒癌犯了,dinic 80何必呢。

Day2

T1:航空管制

很神,但是是贪心。拓扑一下然后直接贪心。

在不看题解下拿了80(二分答案+乱搞)

T2:旅行路线

很懒,裸插头dp,不想捉。

NOI2011

Day1

T1:兔农

很久以前过的了,忘了。

T2:智能车比赛

很SB的水题,最短路,建图叉积一下,貌似我写麻烦了。

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #include <cmath>
  5 #include <queue>
  6 #include <cstdlib>
  7  
  8 #define LL long long
  9 #define sqr(x) ((x)*(x))
 10 #define N 8010
 11 #define p E[i].x
 12  
 13 using namespace std;
 14  
 15 struct edge{
 16     int x,to;
 17     long double v;
 18 }E[2000010];
 19  
 20 struct node{
 21     int x,y,id;
 22     
 23     void print(){
 24         printf("(%d,%d)",x,y);
 25     }
 26     
 27     void scan(){
 28         scanf("%d%d",&x,&y);
 29     }
 30 }S,T,P[100010];
 31  
 32 int tot;
 33 queue<int> q;
 34  
 35 struct road{
 36     node Lu,Ld,Ru,Rd;
 37     
 38     void scan(){
 39         Ld.scan();
 40         Ru.scan();
 41         Lu=(node){Ld.x,Ru.y};
 42         Rd=(node){Ru.x,Ld.y};
 43         Ld.id=++tot; P[tot]=Ld;
 44         Lu.id=++tot; P[tot]=Lu;
 45         Rd.id=++tot; P[tot]=Rd;
 46         Ru.id=++tot; P[tot]=Ru;
 47     }
 48 }L[N];
 49  
 50 int n,totE;
 51 int g[N];
 52 double V;
 53 long double dis[N];
 54 bool v[N];
 55  
 56 double dist(node a,node b){
 57     return sqrt(sqr((LL)(a.x-b.x))+sqr((LL)(a.y-b.y)));
 58 }
 59  
 60 LL cross(node a,node b,node c){
 61     return (c.x-a.x)*(b.y-a.y)-(b.x-a.x)*(c.y-a.y);
 62 }
 63  
 64 bool cut(node a,node b,node c,node d){
 65     if(cross(a,c,b)*(LL)cross(a,d,b)>=0) return 0;
 66     if(cross(c,a,d)*(LL)cross(c,b,d)>=0) return 0;
 67     return 1;
 68 }
 69  
 70 bool check(node a,node b){
 71     for(int i=1;i<=n;i++){
 72         if(cut(a,b,L[i].Ld,L[i].Lu)) return 0;
 73         if(cut(a,b,L[i].Lu,L[i].Ru)) return 0;
 74         if(cut(a,b,L[i].Rd,L[i].Ru)) return 0;
 75         if(cut(a,b,L[i].Ld,L[i].Rd)) return 0;
 76     }
 77     return 1;
 78 }
 79  
 80 void addedge(node a,node b){
 81     int x=a.id,y=b.id;
 82     long double d=dist(a,b);
 83     E[++totE]=(edge){y,g[x],d}; g[x]=totE;
 84     E[++totE]=(edge){x,g[y],d}; g[y]=totE;
 85 }
 86  
 87 void buildgraph(node now){
 88     node up=(node){now.x,now.y+1},down=(node){now.x,now.y-1};
 89     for(int j=1;j<=tot;j++){
 90         if(cross(now,P[j],up)<=0 && cross(now,P[j],down)>=0);
 91         if((j&1)==0 && cross(now,P[j],up)<0) up=P[j];
 92         if((j&1) && cross(now,P[j],down)>0) down=P[j];
 93         if((j&1)==0 && P[j].x>=T.x){
 94             if(cross(now,T,up)<=0 && cross(now,T,down)>=0){
 95                 printf("%.10lf
",dist(S,T)/V);
 96                 exit(0);
 97             }
 98         }
 99     }
100 }
101  
102 void buildgraph2(node now){
103     node up=(node){now.x,now.y+1},down=(node){now.x,now.y-1};
104     for(int j=tot;j>=1;j--){
105         if(cross(now,P[j],up)>=0 && cross(now,P[j],down)<=0)
106             addedge(now,P[j]);
107         if((j&1)==0 && cross(now,P[j],up)>0) up=P[j];
108         if((j&1) && cross(now,P[j],down)<0) down=P[j];
109     }
110 }
111  
112 int main(){
113 //    freopen("car2.in","r",stdin);
114     freopen("noi2011_car.in","r",stdin);
115     freopen("noi2011_car.out","w",stdout);
116     scanf("%d",&n);
117     for(int i=1;i<=n;i++) L[i].scan();
118     S.scan(); S.id=tot+1;
119     T.scan(); T.id=tot+2;
120     if(S.x>T.x) swap(S,T);
121     scanf("%lf",&V);
122     for(int i=1;i<=tot;i++){
123         node up=(node){P[i].x,P[i].y+1},down=(node){P[i].x,P[i].y-1};
124         for(int j=i+1;j<=tot;j++){
125             if(cross(P[i],P[j],up)<=0 && cross(P[i],P[j],down)>=0)
126                 addedge(P[i],P[j]);
127             if((j&1)==0 && cross(P[i],P[j],up)<=0) up=P[j];
128             if((j&1) && cross(P[i],P[j],down)>=0) down=P[j];
129         }
130     }
131     int st=0,ed=0;
132     for(int i=1;i<=tot;i++){
133         if(P[i].x==S.x&&P[i].y==S.y) st=i;
134         if(P[i].x==T.x&&P[i].y==T.y) ed=i;
135     }
136     buildgraph(S);
137     for(int i=1;i<=tot+2;i++) dis[i]=1e50;
138     q.push(st); dis[st]=0;
139     while(!q.empty()){
140         int x=q.front(); q.pop();
141         v[x]=0;
142         for(int i=g[x];i;i=E[i].to)
143             if(dis[p]>dis[x]+E[i].v){
144                 dis[p]=dis[x]+E[i].v;
145                 if(!v[p]) q.push(p),v[p]=1;
146             }
147     }
148     printf("%.10lf
",(double)(dis[ed]/V));
149     return 0;
150 }
View Code

T3:阿狸的打字机

树链剖分维护fail树,不错的经典题

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <queue>
  5 #include <vector>
  6  
  7 #define N 100010
  8 #define MP(x,y) make_pair(x,y)
  9 #define debug(x) cout<<#x<<" = "<<x<<endl;
 10 #define fir first
 11 #define sec second
 12  
 13 using namespace std;
 14  
 15 void file(){
 16     freopen("noi2011_type.in","r",stdin);
 17     freopen("noi2011_type.out","w",stdout);
 18 }
 19  
 20 struct node{
 21     node *ch[26],*fail,*fa,*next[26];
 22     int v,id;
 23 }*root,*pre[N];
 24  
 25 int n,tot,sumv[N],L[N],R[N],g[N],totE,cnt,tott,ansv[N];
 26 char S[N];
 27 vector<pair<int,int> > ask[N];
 28  
 29 struct edge{
 30     int x,to;
 31 }E[N<<1];
 32  
 33 queue<node*> q;
 34  
 35 void ade(int x,int y){
 36     E[++totE]=(edge){y,g[x]}; g[x]=totE;
 37 }
 38  
 39 int qsum(int x){
 40     int ans=0;
 41     for(;x>0;x-=(x&-x)) ans+=sumv[x];
 42     return ans;
 43 }
 44  
 45 void add(int x,int v){
 46     for(;x<=tot;x+=(x&-x)) sumv[x]+=v;
 47 }
 48  
 49 void getfail(){
 50     q.push(root);
 51     while(!q.empty()){
 52         node* tmp=q.front(); q.pop();
 53         tmp->id=++tot;
 54         if(tmp!=root) ade(tmp->fail->id,tmp->id);
 55         for(int t=0;t<26;t++){
 56             if(tmp->ch[t]!=NULL){
 57                 if(tmp==root) tmp->ch[t]->fail=root;
 58                 else tmp->ch[t]->fail=tmp->fail->ch[t];
 59                 q.push(tmp->ch[t]);
 60             }
 61             else{
 62                 if(tmp==root) tmp->ch[t]=root;
 63                 else tmp->ch[t]=tmp->fail->ch[t];
 64             }
 65         }
 66     }
 67 }
 68  
 69 #define p E[i].x
 70  
 71 void dfs(int x){
 72     L[x]=++tott;
 73     for(int i=g[x];i;i=E[i].to) dfs(p);
 74     R[x]=tott;
 75 }
 76  
 77 void solve(node* x){
 78     add(L[x->id],1);
 79     for(int i=ask[x->id].size()-1;~i;i--){
 80         int t=ask[x->id][i].fir;
 81         ansv[ask[x->id][i].sec]=qsum(R[t])-qsum(L[t]-1);
 82     }
 83     for(int t=0;t<26;t++)
 84         if(x->next[t]!=NULL) solve(x->next[t]);
 85     add(L[x->id],-1);
 86 }
 87  
 88 int main(){
 89     file();
 90     scanf("%s",S);
 91     root=new node();
 92     node* tmp=root;
 93     for(int i=0,len=strlen(S);i<len;i++){
 94         if(S[i]=='P') pre[++cnt]=tmp;
 95         else if(S[i]=='B') tmp=tmp->fa;
 96         else{
 97             int t=S[i]-'a';
 98             if(tmp->ch[t]==NULL){
 99                 tmp->ch[t]=new node();
100                 tmp->next[t]=tmp->ch[t];
101             }
102             tmp->ch[t]->fa=tmp;
103             tmp=tmp->ch[t];
104         }
105     }
106     getfail();
107     dfs(root->id);
108     scanf("%d",&n);
109     for(int i=1,x,y;i<=n;i++){
110         scanf("%d%d",&x,&y);
111         ask[pre[y]->id].push_back(MP(pre[x]->id,i));
112     }
113     solve(root);
114     for(int i=1;i<=n;i++)
115         printf("%d
",ansv[i]);
116     fclose(stdin);
117     fclose(stdout);
118     return 0;
119 }
View Code

Day2

T1:道路修建

233这题。。。。

T2:NOI 嘉年华

读不懂

T3:兔子和蛋蛋

没看

原文地址:https://www.cnblogs.com/lawyer/p/4592388.html