uoj14 DZY Loves Graph
看起来很有趣的样子。。
Solution
如果没有恢复操作,那么插入和删除的总量是的,所以可以暴力删边。只会删除大边,不会删除小边,所以不存在断开需要重新链接的情况。用一个栈实现就行。
MD撤销指的是撤销前一次操作qwq。。'
折样的话,把操作离线,就可以知道下一个操作是不是return。如果是的话特殊处理一下就好了。。
Code
1 |
|
1 |
|
可持久化的做法,MLE自不必说,居然还有WA?但是不想调了。。
uoj21 缩进优化
答案居然不是单峰的qwq
但是对于所有/ts不变的块内的最小值是单峰的,答案肯定在那里面。
于是我会了一种的做法。。MDZZ
Solution
整除不禁让人想起了经典的数论分块。。
要分块就要想办法把这个mod消掉
只要对的个数搞一个前缀和就可以得到分啦!!
然后呢?
为什么要枚举呢?枚举啊!然后就AC了。
1 |
|
uoj22 外星人
- 在模的过程中,值一定是越来越小的,绝对值越来越大。
- 然后我想想?
- 大的永远不会影响,可以用组合数计算
Solution
先想如何求最大值??
一个点后面所有比它大的值都不会影响答案。
一个有效的操作序列是一个下降序列。
相当于排完序求一个子序列,膜完剩下最大。然后随便DP,就有36分。
依然延续求第一问的思路,现在考虑如何求出方案数。
其实都是一样的,也就是分两种情况讨论一下:废掉这个,还是用掉这个。
1 |
|
弄明白之后才感觉自己真SB。
跳蚤国王下江南
毒瘤啊。。
uoj31 猪猪侠再战括号序列
直接暴力构造应该就有50分吧。。
并不是。。暴力构造可能会有步。。zz.
最多只需要转下。
用Splay维护就A了?2333
可以看成一次操作需要成全一对
我忽略了什么?为什么毫无思路??????
1 | def fuck(): |
Solution
正解的思路,和暴力构造是一个意思。
只是找左括号的时候要找右边第一个。
你猜怎么着?中间都是右括号,根本不会变,翻转变成的了!!!
而左括号的位置是有单调性的!!!
Tips
错误的估计了暴力的正确性qwq 否则应该还是能想出来的
Code
1 |
|
uoj32 跳蚤公路
先SCC一下。
求出每个SCC的最大最小值
一个点的答案就是从1能到、且能到v的scc中去一个交集
还是二分吗
折样的话这一部分总复杂度是的
然后就能搞了??
没法直接二分啊XD
应该可以二分。。但是会很麻烦啊qwq
## Tips
发现满足可二分性质的东西,看看是否可以列成一个可以解的式子,由判定转为求值
为什么不会分成两段????
Solution
真是一道好题。。。。。
写一个详细的Solution吧。。。
开始口胡
首先题意中的挣钱道路就是负权回路。判断一张图有没有负权回路是“经典问题”,可以用Bellman-Ford来做。再想想,不存在负权回路的应该是数轴上一段连续的区间,所以满足可二分性。至于怎么二分?先代入一下最大值,再代入一下最小值,如果是负的就二分找正的,否则二分找负的。
直接做复杂度是的,显然不科学。
考虑一点性质:一个SCC里面,所有点不存在负权回路的上下界都应该相同。所以可以对每个SCC单独搞,计算答案的时候,找出所有能到达的SCC把上下界取交集即可。。最后应该能了吧。。。
这个应该能做啊。。但我想出来之后去看题解发现这个似乎不科学???
口胡结束
于是学习了一番std
判断是否有负权回路,经典做法是Bellman-Ford。在第次松弛如果依然有被松弛的说明它就在一个含有负权回路的路径上。
而现在还存在这一个系数,那就设表示走了步,系数为,到了点的最短路,转移显然。
最后要满足的条件,是
这个条件怎么解呢?
首先显然不同的是独立的,那就固定,然后,再固定一维。可行区间就是对每个解出来最后把范围取个交集。
最后考虑这个怎么解。其实就是对每个解出来把范围取个并集。
先并集后交集这个很难搞,那就转化成对补集先交集再并集。补集的并集也没什么好办法,用vector存下来就行了。
最后计算答案,就枚举一下所有从1能到,而且能到的点,把的那些补集都插入到一个vector。最后把这些补集取个并集,再补集一下就是答案。这个部分就简单多了:因为众所周知最后的答案一定是一个连续的区间,那么补集之多只会出现一段的空缺。找出这一段,就是最后的答案了。
Code
1 |
|
uoj33 树上gcd
看着就好神啊。。。。。
直接点分治??分个头。。
怎么做怎么做??????????
Solution
官方题解给了两种做法,和
这种做法复杂度不优秀但是比较好写,也比较神奇。
要求的数目,可以转化成的数目,最后反演一下就好了!!!(蒟蒻觉得很腻害!)
首先在一条链上的比较好做。。这一部分不用反演。一个点对答案的贡献是区间+1,这样用差分实现,最后一遍前缀和就行了。
剩下的部分,也就是不是直上直下的点对,咋做?
对于,大力dp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
struct Istream {
Istream() {
freopen("input","r",stdin);
std::string fileName(__FILE__),name=fileName.substr(0,fileName.find('.'));
freopen((name+".in").c_str(),"r",stdin);
freopen((name+".out").c_str(),"w",stdout);
}
template <class T>
Istream &operator >>(T &x) {
static char ch;static bool neg;
for(ch=neg=0;ch<'0' || '9'<ch;neg|=ch=='-',ch=getchar());
for(x=0;'0'<=ch && ch<='9';(x*=10)+=ch-'0',ch=getchar());
x=neg?-x:x;
return *this;
}
template <class T>
operator T() {
static T x;
*this>>x;
return x;
}
}is;
struct Ostream {
template <class T>
Ostream &operator <<(T x) {
x<0 && (putchar('-'),x=-x);
static char stack[233];static int top;
for(top=0;x;stack[++top]=x%10+'0',x/=10);
for(top==0 && (stack[top=1]='0');top;putchar(stack[top--]));
return *this;
}
Ostream &operator <<(char ch) {
putchar(ch);
return *this;
}
}os;
const int MAXN=2e5+11;
const int SB=10;
#define int64 long long
std::vector<int> son[MAXN],h[MAXN];
int64 Ans[MAXN];
int dep[MAXN],fa[MAXN],f[MAXN][SB+1],g[MAXN][SB+1];
void DFS(int pos) {
static int stack[MAXN],top;
stack[++top]=pos;
for(int u : son[pos]) {
DFS(u);
}
if(pos!=1) {
//f 正好的 g 差1的
for(int d=1;d<=SB;++d) {//必须要算满SB 因为还有下面的!!见2、3行
g[stack[std::max(top-d+1,0)]][d]+=f[pos][d]+1;
Ans[d]+=(int64)f[fa[pos]][d]*g[pos][d];
f[fa[pos]][d]+=g[pos][d];
}
h[pos].push_back(1);
if(h[fa[pos]].size()<h[pos].size()) {
std::swap(h[fa[pos]],h[pos]);
}
std::vector<int> &a=h[fa[pos]],&b=h[pos];
int sizeA=a.size(),sizeB=b.size();
if(sizeA>SB && sizeB>SB) {
for(int d=SB+1;d<=sizeB;++d) {
int sumA=0;
for(int len=d;len<=sizeA;sumA+=a[sizeA-len],len+=d);
int sumB=0;
for(int len=d;len<=sizeB;sumB+=b[sizeB-len],len+=d);
Ans[d]+=(int64)sumA*sumB;
}
}
for(int d=1;d<=sizeB;a[sizeA-d]+=b[sizeB-d],++d);
b.clear();
}
top--;
}
int main() {
int n=is;
static int64 cnt[MAXN];
for(int i=2;i<=n;++i) {
dep[i]=dep[fa[i]=is]+1;
++cnt[1];--cnt[dep[i]+1];
son[fa[i]].push_back(i);
}
for(int i=1;i<=n-1;cnt[i]+=cnt[i-1],++i);
DFS(1);
for(int i=n-1;i>=1;--i) {
for(int j=i*2;j<=n-1;j+=i) {
Ans[i]-=Ans[j];
}
}
for(int i=1;i<=n-1;++i) {
Ans[i]+=cnt[i];
os<<Ans[i]<<'\n';
}
return 0;
}
uoj48 核聚变反应强度
大水题啊。。不写了。。
uoj49 铀仓库
可以三分套二分吧。。
不需要三分时间,只需要二分距离!
MD各种爆int爆ll被卡晕了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
struct Istream {
Istream() {
freopen("input","r",stdin);
std::string fileName(__FILE__),name=fileName.substr(0,fileName.find('.'));
freopen((name+".in").c_str(),"r",stdin);
freopen((name+".out").c_str(),"w",stdout);
}
template <class T>
Istream &operator >>(T &x) {
static char ch;static bool neg;
for(ch=neg=0;ch<'0' || '9'<ch;neg|=ch=='-',ch=getchar());
for(x=0;'0'<=ch && ch<='9';(x*=10)+=ch-'0',ch=getchar());
x=neg?-x:x;
return *this;
}
template <class T>
operator T() {
static T x;
*this>>x;
return x;
}
}is;
struct Ostream {
template <class T>
Ostream &operator <<(T x) {
x<0 && (putchar('-'),x=-x);
static char stack[233];static int top;
for(top=0;x;stack[++top]=x%10+'0',x/=10);
for(top==0 && (stack[top=1]='0');top;putchar(stack[top--]));
return *this;
}
Ostream &operator <<(char ch) {
putchar(ch);
return *this;
}
}os;
const int MAXN=5e5+11;
int n,a[MAXN],x[MAXN];
long long tlim,pref_sum[MAXN];
bool check(long long cnt) {
if(cnt==a[0]) {
return 1;
} else {
static int chs[MAXN];
std::fill(chs+1,chs+1+n,0);
int l=1,r=1;chs[1]=a[1];long double tuse=0;
for(long long sum=a[1];sum<cnt;) {
++r;
chs[r]=sum+a[r]<=cnt?a[r]:cnt-sum;
sum+=chs[r];
tuse+=(long double)(chs[r])*(x[r]-x[1]);
}
if(2*tuse<=tlim) return 1;
for(int i=2;i<=n;++i) {
tuse+=(long double)(x[i]-x[i-1])*((pref_sum[i-1]-pref_sum[l]+chs[l])-(pref_sum[r-1]-pref_sum[i-1]+chs[r]));
while(x[i]-x[l]>x[r]-x[i]) {
int d=std::min(a[r]-chs[r],chs[l]);
tuse+=(long double)(d)*(x[l]+x[r]-2*x[i]);
(chs[l]-=d)==0 && ++l;
(chs[r]+=d)==a[r] && ++r;
}
if(2*tuse<=tlim) return 1;
}
return 0;
}
}
int main() {
is>>n>>tlim;
for(int i=1;i<=n;is>>x[i++]);
x[n+1]=2e9+1e8;
for(int i=1;i<=n;pref_sum[i]=pref_sum[i-1]+(a[i]=is),++i);
long long L=a[0]=*std::max_element(a+1,a+1+n),R=pref_sum[n];
while(L!=R) {
long long M=(L+R+1)>>1;
check(M)?L=M:R=M-1;
}
os<<L<<'\n';
return 0;
}
//WA??
uoj50 链式反应
现在我知道这道题是fft。。然后呢??
每个中子呈树状展开,最后有多少棵(带编号)不同的树
转移明显是没有后效性的。。吗并不是。。因为死光的操作很烦人。。
一个点爆炸后面有个完好的方案数
枚举中子打到的位置
可以把那个分成三段
再枚举射死多少
再枚举在三段里面分别射死多少
就可以DP了吧
复杂度
不行。。
MDZZ
要么这个囧-2333原子变为了囧-2334 并不再参与后续反应
又tm没看题目!!!!!
那就好做点了吗?
表示的答案。
转移的时候不枚举编号,枚举梓树大小!!!还是用树的思维来思考,从大小来考虑好一些。因为大小是比编号更加重要的因素,而知道编号没法推出大小,但是知道大小可以随便重编号!!!树树树!!!
40pts
1 |
|
uoj51 元旦三侠的游戏
Solution
如果小一些的话就能做了吗。
Tips
调用sqrt()不总能达到想要的效果。。要求高的整数开方可以自行二分。。。。
Code
1 |
|