更新博客系列

来源:互联网 发布:淘宝服装一件代发货源 编辑:程序博客网 时间:2024/06/10 19:56

好久不更新博客了……
来更新一发!
[bzoj4531]路径
dp[i][j][k][l]表示这个东西有j个左括号,当前走了i步,上次在k节点,是不是单独的一个0.
然后就暴力分类大讨论即可。

#include <bits/stdc++.h>#define Rep(i,n) for(int i = 1;i <= n;++ i)#define v edge[i].tousing namespace std;int n,m,K;bool w[30][30];typedef long long LL;const int mod = (int)1e9 + 7;LL f[32][32][32][2];char s[44];bool dig(int x){return x >= '0' && x <= '9';}void Add(LL &x,LL y){x = x + y;if(x >= mod)x %= mod;}void dp(){    for(int i = 1;i <= n;++ i)        if(s[i] == '0')f[1][0][i][1] = 1;        else if(s[i] > '0' && s[i] <= '9')f[1][0][i][0] = 1;        else if(s[i] == '-')f[1][0][i][0] = 1;        else if(s[i] == '(')f[1][1][i][0] = 1;    //Init    for(int i = 1;i < K;++ i)    {        for(int j = 0;j <= i;++ j) //j:未匹配的括号数 *****************        {            for(int k = 1;k <= n;++ k)            {                for(int p = 1;p <= n;++ p) //枚举k的前驱                 {                    if(!w[k][p])continue;                    if(dig(s[p]))                    {                        if(dig(s[k]))Add(f[i + 1][j][p][0],f[i][j][k][0]);//4.1                        else if(s[k] != ')')Add(f[i + 1][j][p][s[p] == '0'],f[i][j][k][0]);//3.1                        //if(s[p] == '0' && !dig(s[k]) && s[k] != ')')Add(f[i + 1][j][p][1],f[i][j][k][0]);                    }                    else if(s[p] == '*' || s[p] == '+' || s[p] == '-' || s[p] == '/')                    {                        if(dig(s[k]))//4.2                        {                            Add(f[i + 1][j][p][0],f[i][j][k][0]);                            Add(f[i + 1][j][p][0],f[i][j][k][1]);                        }                        else if(s[k] == '(' && s[p] == '-')Add(f[i + 1][j][p][0],f[i][j][k][0]);//1.1                        else if(s[k] == ')')Add(f[i + 1][j][p][0],f[i][j][k][0]);//2.1                    }                    else if(s[p] == '(')                    {                        if(dig(s[k]));                        else if(s[k] == ')');                        else Add(f[i + 1][j + 1][p][0],f[i][j][k][0]);//1.2 + 3.2                    }                    else if(s[p] == ')' && j > 0)                    {                        if(s[k] == '(' || s[k] == '*' || s[k] == '+' || s[k] == '-' || s[k] == '/');//如果s[k]不合法                         else if(s[k] == ')')Add(f[i + 1][j - 1][p][0],f[i][j][k][0]);//2.2                        else Add(f[i + 1][j - 1][p][0],f[i][j][k][0]),Add(f[i + 1][j - 1][p][0],f[i][j][k][1]);//4.3(dig)                    }                }            }        }    }}LL sum(){    LL cur = 0;    Rep(i,n)if(dig(s[i]) || s[i] == ')')Add(cur,f[K][0][i][0]),Add(cur,f[K][0][i][1]);    return cur;}int main(){    scanf("%d%d%d",&n,&m,&K);    scanf("%s",s + 1);    while(m --){int a,b;scanf("%d%d",&a,&b);w[a][b] = w[b][a] = 1;}    dp();    printf("%lld\n",sum());    return 0;}

bzoj4184: shallot
考虑一个事情就是,线性基是很难删除的。
那么我们可以用线段树分治来做这个事情。
我们用一棵时间线段树来表示每个节点的存在时间。
可以注意到的是,每个节点必然存在于连续的一段中。
我们把对应位置的区间打上永久化的标记,表示[l,r]这段区间中,这个节点是存在的。
这样的话,我们对于叶子节点[a,a],只需要考虑它到根路径上的所有节点上的标记即可知道[a,a]时刻的答案。
那么我们对线段树进行一次dfs,在dfs的过程中维护极简线性基即可。
总的复杂度是O(nlognlogW)
维护只有插入操作的极简线性基?
增量法:如果我们已经维护了{a1,a2,a3...,ak}这样一组极简线性基,现在有一个新的基可以加入,那么我们要新加入一个东西作为新的基。
考虑到加入这个基之后,实际上低位的线性基中最高位的1并不一定是唯一的了,这时我们就用低位的先消掉这个基的1的位。
这样,这个基能消的就都被消掉了,我们用这个基去消更高位的基即可。
最后把所有的线性基异或起来就是答案。

#include<bits/stdc++.h>#define Rep(i,n) for(int i = 1;i <= n;i ++)#define mid (l + r >> 1)#define lson x << 1,l,mid#define rson x << 1 | 1,mid + 1,rusing namespace std;int m,n,ql,qr,cur_val;const int N = 500001;set<pair<int,int> >s;vector<int>vec[N << 2];struct Node{    int a[32];    int &operator[](int x)    {        return a[x];    }}c;void Ins(int x,Node &cur){    int pos = -1;    for(int i = 30;~ i;i --)    {        if(!cur[i] && x & (1 << i)){cur[i] = x;pos = i;break;}        else if(x & (1 << i))x ^= cur[i];    }    if(~pos)    {        for(int i = pos - 1;~ i;i --)        {            if((cur[pos] & (1 << i)) && cur[i])                cur[pos] ^= cur[i];        }        for(int i = 30;i != pos;-- i)        {            if(cur[i] & (1 << pos))            {                cur[i] ^= cur[pos];            }        }    }}void Modify(int x,int l,int r){    if(ql <= l && r <= qr)    {        vec[x].push_back(cur_val);        return ;    }    if(ql <= mid)Modify(lson);    if(mid < qr)Modify(rson);}void solve(int x,int l,int r,Node cur){    int sz = vec[x].size();    for(int i = 0;i < sz;++ i)Ins(vec[x][i],cur);    if(l == r)    {        int val = 0;        for(int i = 30;~ i;i --)val ^= cur[i];        printf("%d\n",val);        return ;    }    solve(lson,cur),solve(rson,cur);}int main (){    scanf("%d",&n);    Rep(i,n)    {        int x;        scanf("%d",&x);        if(x > 0)s.insert(make_pair(x,i));        else        {            x = -x;            pair<int,int> q = *s.lower_bound(make_pair(x,0));            ql = q.second,qr = i - 1;            cur_val = x;            Modify(1,1,n);            s.erase(q);        }    }    for(set<pair<int,int> >:: iterator it = s.begin();it != s.end();++ it)    {        ql = (*it).second,qr = n,cur_val = (*it).first;        Modify(1,1,n);    }    solve(1,1,n,c);    return 0;}
0 0