bzoj4059 [Cerc2012]Non-boring sequences && bzoj5200 [NWERC2017]Factor-Free Tree

https://konnyakuxzy.github.io/BZPRO/JudgeOnline/4059.html

https://cn.vjudge.net/problem/Gym-100624D

根本不会。。。

似乎有很高妙的分治做法啊!https://www.cnblogs.com/forever97/p/bzoj4059.html

就是说,如果当前区间为[l,r],存在一个i满足pre[i]<l&&nxt[i]>r,那么任意一个[l,r]的子区间,只要包含i点就不无聊,因此只需要再检验[l,i-1]和[i+1,r]即可

复杂度n*log就是因为倒过来就是启发式合并的过程。。。

以前代码很奇怪不知道怎么回事也A掉了。。。

if(i==j)    break;
i++;
if(pre[i]<l&&nxt[i]>r)    return solve(l,i-1)&&solve(i+1,r);
if(i==j)    break;
j--;
if(pre[j]<l&&nxt[j]>r)    return solve(l,j-1)&&solve(j+1,r);
View Code
 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<vector>
 5 #include<map>
 6 using namespace std;
 7 #define fi first
 8 #define se second
 9 #define mp make_pair
10 #define pb push_back
11 typedef long long ll;
12 typedef unsigned long long ull;
13 typedef pair<int,int> pii;
14 int n,T,a[200100];
15 int pre[200100],nxt[200100];
16 map<int,int> ma;
17 bool solve(int l,int r)
18 {
19     if(l>=r)    return 1;
20     int i,j;
21     for(i=l,j=r;;)
22     {
23         if(pre[i]<l&&nxt[i]>r)    return solve(l,i-1)&&solve(i+1,r);
24         i++;
25         if(i>j)    break;
26         if(pre[j]<l&&nxt[j]>r)    return solve(l,j-1)&&solve(j+1,r);
27         j--;
28         if(i>j)    break;
29     }
30     return 0;
31 }
32 int main()
33 {
34     int i;
35     scanf("%d",&T);
36     while(T--)
37     {
38         scanf("%d",&n);
39         for(i=1;i<=n;i++)    scanf("%d",&a[i]);
40         ma.clear();
41         for(i=1;i<=n;i++)
42         {
43             pre[i]=ma.count(a[i])?ma[a[i]]:0;
44             ma[a[i]]=i;
45         }
46         ma.clear();
47         for(i=n;i>=1;i--)
48         {
49             nxt[i]=ma.count(a[i])?ma[a[i]]:n+1;
50             ma[a[i]]=i;
51         }
52         puts(solve(1,n)?"non-boring":"boring");
53     }
54     return 0;
55 }

也有很高妙的扫描线做法啊!https://blog.csdn.net/PoPoQQQ/article/details/46380617


https://konnyakuxzy.github.io/BZPRO/JudgeOnline/5200.html

https://cn.vjudge.net/problem/Gym-101623F

做法跟上面那题几乎是一样的

仍然不会。。。

做法是类似的,卡在”区间内有多个可作为根的位置时,如何选择“上了

上网查了一下,发现怎样选择并不会影响答案。。。

证明很简单:假设已经得到了区间内一组以a为根的合法解,b也是一个合法根,直接把这棵树的根改为b,那么显然只有a到b的链上的所有边的两个端点的父亲-祖先关系反了一下,显然这条链上端点的值两两互质,因此这样子换根之后也是合法解

还有一点:我自己想的是每次分治直接分解质因数然后怎么怎么样,很慢,可能被卡常(质因数分解n^(1/4)吧?)

然而,可以直接线筛出1e7内每个数的最小质因子。。。然后分解质因子复杂度只要一个log

而且,只需要预处理每个数的上一个和下一个与其不互质的数位置即可。。。感觉常数要小不少啊

错误记录:

1.已经发现了需要单独记录f[t],然后while才能除以的是同一个数(就是需要69行),但是只改了一半(没改81行)

2.LA上有多组数据,但是我没有完整地清空(WA了很多发,包括61行,87行(需要fa[..]=0))

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<vector>
 5 #include<map>
 6 using namespace std;
 7 #define fi first
 8 #define se second
 9 #define mp make_pair
10 #define pb push_back
11 typedef long long ll;
12 typedef unsigned long long ull;
13 typedef pair<int,int> pii;
14 bool nprime[10000010];
15 int prime[1000100],len,f[10000010];
16 int n,a[1001000];
17 int pre[1001000],nxt[1001000];
18 map<int,int> ma;
19 bool fl;
20 int fa[1001000];
21 int solve(int l,int r)
22 {
23     if(l>r)    return 0;
24     if(l==r)    return l;
25     int i,j;
26     for(i=l,j=r;;)
27     {
28         if(pre[i]<l&&nxt[i]>r)
29         {
30             fa[solve(l,i-1)]=i;
31             fa[solve(i+1,r)]=i;
32             return i;
33         }
34         i++;
35         if(i>j)    break;
36         if(pre[j]<l&&nxt[j]>r)
37         {
38             fa[solve(l,j-1)]=j;
39             fa[solve(j+1,r)]=j;
40             return j;
41         }
42         j--;
43         if(i>j)    break;
44     }
45     fl=1;
46     return 0;
47 }
48 int main()
49 {
50     int i,j,t,q;
51     for(i=2;i<=10000000;i++)
52     {
53         if(!nprime[i])    prime[++len]=i,f[i]=i;
54         for(j=1;j<=len&&i*prime[j]<=10000000;j++)
55         {
56             nprime[i*prime[j]]=1;f[i*prime[j]]=prime[j];
57             if(i%prime[j]==0)    break;
58         }
59     }
60     while(scanf("%d",&n)==1){
61     fl=0;
62     for(i=1;i<=n;i++)    scanf("%d",&a[i]);
63     ma.clear();
64     for(i=1;i<=n;i++)
65     {
66         t=a[i];pre[i]=0;
67         while(t!=1)
68         {
69             q=f[t];
70             pre[i]=max(pre[i],ma.count(q)?ma[q]:0);
71             ma[q]=i;
72             while(t%q==0)    t/=q;
73         }
74     }
75     ma.clear();
76     for(i=n;i>=1;i--)
77     {
78         t=a[i];nxt[i]=n+1;
79         while(t!=1)
80         {
81             q=f[t];
82             nxt[i]=min(nxt[i],ma.count(q)?ma[q]:n+1);
83             ma[q]=i;
84             while(t%q==0)    t/=q;
85         }
86     }
87     fa[solve(1,n)]=0;
88     if(fl)    puts("impossible");
89     else
90     {
91         for(i=1;i<=n;i++)
92         {
93             printf("%d",fa[i]);
94             if(i!=n)    putchar(' ');
95         }
96         puts("");
97     }}
98     return 0;
99 }
View Code

 

posted @ 2018-08-26 20:59  hehe_54321  阅读(258)  评论(0编辑  收藏  举报
AmazingCounters.com