Questions surface: https://www.cnblogs.com/Juve/articles/11602450.html
in:
Optimization modified by difference
Dimensional difference: to (x1, y1), (x2, y2) plus s:
$d[x1][y1]+=s,d[x1][y2+1]-=s,d[x2+1][y1]-=s,d[x2+1][y2+1]+=s$
Defines an array of two differential d1, d2, respectively, and recording the differential vertical column hypotenuse
$d1[r][c]+=s,d1[r+l-1][c]-=s,d2[r][c+1]-=s,d2[r+l-1][c+l-1]+=s$
Statistics are seeking two prefixes and
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #define int long long using namespace std; const int MAXN=1e3+5; int n,q,a[MAXN][MAXN],b[MAXN][MAXN],c[MAXN][MAXN],d[MAXN][MAXN],ans=0; int d1[MAXN][MAXN],d2[MAXN][MAXN]; signed main(){ scanf("%lld%lld",&n,&q); while(q--){ int r,c,l,s; scanf("%lld%lld%lld%lld",&r,&c,&l,&s); int N=min(n,r+l-1),M=min(n,c+l-1); d1[r][c]+=s,d1[N+1][c]-=s; d2[r][c+1]-=s,d2[N+1][M+2]+=s; } for(int i=1;i<=n;++i){ for(int j=1;j<=n;++j){ a[i][j]=(a[i-1][j]+d1[i][j]); b[i][j]=(b[i-1][j-1]+d2[i][j]); c[i][j]=a[i][j]+b[i][j]; d[i][j]=d[i][j-1]+c[i][j]; } } for(int i=1;i<=n;++i){ for(int j=1;j<=n;++j) ans^=d[i][j]; } printf("%lld\n",ans); return 0; }
v:
Search every case, the repeated use of bit map memory
Note that a length of an odd number is determined, map timeout hash table can be used
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define re register using namespace std; int n,k,sta=0; char ch[35]; struct hash_map{ int pre[40000000],cnt; struct node{ int nxt,to,w; double v; }e[6000000]; double &operator[](int sta){ int key=1LL*sta%30000019; for(int i=pre[key];i;i=e[i].nxt) if(e[i].to==sta) return e[i].v; e[++cnt].nxt=pre[key];e[cnt].to=sta;;e[cnt].v=-1.0; pre[key]=cnt; return e[cnt].v; } }mp; inline double dfs(re int x,re int st){ if(x==n-k) return 0.0; if(mp[st]!=-1) return mp[st]; mp[st]=0; re double sum=0.0; for(re int i=1;i<=x>>1;i++){ re int con1=st>>i-1&1,con2=st>>x-i&1; re int to1=st>>1&~((1<<i-1)-1)|st&(1<<i-1)-1; re int to2=st>>1&~((1<<x-i)-1)|st&((1<<x-i)-1); sum+=2.0*max(dfs(x-1,to1)+con1,dfs(x-1,to2)+con2)/x; } if(x&1){ re int i=x+1>>1; re int to=st>>1&~((1<<i-1)-1)|st&(1<<i-1)-1; re int con=st>>i-1&1; sum+=(dfs(x-1,to)+con)/x; } return mp[st]=sum; } signed main(){ scanf("%d%d",&n,&k); scanf("%s",ch+1); for(re int i=1;i<=n;i++) sta|=(ch[i]=='W')<<n-i; sta|=1<<n; printf("%0.7lf\n",dfs(n,sta)); return 0; }
w:
If we choose a side, give the degree of edge points at both ends plus one, then the first answer is that the degree is odd number of points divided by 2
We define dp [i] [0/1] represent the i-node, no / There are two answers to his father's side of the reverse i
Next we consider the update:
when updating we use two parameters: p and q, dp updated as intermediate step, do not chain to i p represents an endpoint, q i do representative chain end, a certain set i child node is to, so there are:
P = min (P + DP [to] [0], Q + DP [to] [. 1])
Q = min (P + DP [to] [. 1], Q + DP [ to] [0])
wherein p is initialized to (0,0), q is initialized (INF, INF)
explain: here the Add pair corresponding element is added (non-built-in handwriting)!!
and operating means press the pair min comparing the first key, then press the second key comparison
then this step is a combined process:
first of all, i do not chain as an endpoint: to combine two types: If the edges of the child nodes and i flipped, then they would i was tired at the end of the chain to the inside (because i do not flip side with his father, then i will be the endpoints), if the child node and edge i is not turned over, only for the purposes of sub-tree tree, and not as i end path, so there is no update to the expense i endpoint chain
if the chain as an end point i, to merge the two types of the same: if the edge node i flip child, then obviously i May be the end of the chain, provided that this is not a chain before the end i, so i is not used before the end of the chain to the cost of updating; on the contrary, if the child node and edge i is not turned over, that matter is not i endpoint is an endpoint may request i chain, so i have to use the cost of the original chain of endpoints is updated
after traversing the root of all child nodes, update dp:
if i do not flip side with his father. That state dp [i] [0]:
First, as an endpoint chain not i is certainly a possibility, direct comparison
and then, if i is an endpoint of the chain, the edge node i and the parent has not turned over, described in this state i is the real point of singularity, so the first + q status update 1
if i and father's side flip, the same two types of updates:
First of all, i itself as the endpoint of the chain, and because i itself is a singular degree point, it will only be updated q.second + 1 can
also, if i did not own in the following chain as an endpoint, but i did side with the parent node occurs flip, so i became a new point of singularity, while also increasing the chain length, so p.first, p.second were increased to
the final answer is, dp [1] [0] .first / 2, dp [1] [0] .second
#include<iostream> #include<cstdio> #include<cstring> #include<vector> #include<algorithm> using namespace std; const int MAXN=5e5+5; const int inf=0x3f3f3f3f; int n; int to[MAXN<<1],nxt[MAXN<<1],pre[MAXN],flag[MAXN<<1],cnt=0; void add(int u,int v,int val){ ++cnt,to[cnt]=v,nxt[cnt]=pre[u],pre[u]=cnt,flag[cnt]=val; } struct node{ int tim,len; friend node operator + (node a,node b){ return (node){a.tim+b.tim,a.len+b.len}; } friend bool operator < (node a,node b){ return a.tim==b.tim?a.len<b.len:a.tim<b.tim; } }dp[MAXN][2]; node min(node a,node b){ return a<b?a:b; } void dfs(int x,int fa,int fl){ node p={0,0},q={inf,inf}; for(int i=pre[x];i;i=nxt[i]){ int y=to[i]; if(y==fa) continue; dfs(y,x,flag[i]); node a=p,b=q; p=min(a+dp[y][0],b+dp[y][1]); q=min(b+dp[y][0],a+dp[y][1]); } if(fl==2){ dp[x][0]=min(p,q+(node){1,0}); dp[x][1]=min(p+(node){1,1},q+(node){0,1}); } if(fl==1){ dp[x][0]=(node){inf,inf}; dp[x][1]=min(p+(node){1,1},q+(node){0,1}); } if(fl==0){ dp[x][0]=min(p,q+(node){1,0}); dp[x][1]=(node){inf,inf}; } } signed main(){ scanf("%d",&n); for(int i=1,a,b,c,d;i<n;++i){ scanf("%d%d%d%d",&a,&b,&c,&d); if(d==2){ add(a,b,2),add(b,a,2); }else{ if(c==d) add(a,b,0),add(b,a,0); else add(a,b,1),add(b,a,1); } } dfs(1,0,0); printf("%d %d\n",dp[1][0].tim/2,dp[1][0].len); return 0; }